When using Stringee Call API for the first time, you must have a Stringee account. If you do not have a Stringee account, sign up for free here: https://developer.stringee.com/account/register
Create a Project on Stringee Dashboard

Buy a Number (optional)
For app-to-phone, phone-to-app calling, buy a Number from Dashboard. If you only need app-to-app calling, skip this step.

Configure answer_url
For more information on answer_url, read Stringee Call API Overview. You can view answer_url sample code here: https://github.com/stringeecom/server-samples/tree/master/answer_url

If you do not have answer_url, to speed things up you can use the following Project's answer_url:
Project's answer_url for App-to-App call:
https://developer.stringee.com/scco_helper/simple_project_answer_url?record=false&appToPhone=false
Project's answer_url for App-to-Phone call:
https://developer.stringee.com/scco_helper/simple_project_answer_url?record=false&appToPhone=true
(Source code here: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/project_answer_url.php)
When building an application, you should use your own answer_url.

If you do not have a answer_url, to speed things up you can use the following Number's answer_url:
Number's answer_url for Phone-to-App call (The call is routed to Your App which authenticated by USER_ID):
https://developer.stringee.com/scco_helper/simple_number_answer_url?record=true&phoneToPhone=false&to_number=USER_ID
Number's answer_url for Phone-to-Phone call (The call is routed to TO_NUMBER):
https://developer.stringee.com/scco_helper/simple_number_answer_url?record=true&phoneToPhone=true&stringeeNumber=STRINGEE_NUMBER&to_number=TO_NUMBER
(Source code here: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/number_answer_url.php)
When building an application, you should use your own answer_url.
Distribution notice: Starting in June 2026, new versions of the Stringee iOS SDK are released exclusively through Swift Package Manager (SPM). CocoaPods and manual distributions are retained for legacy integrations only and no longer receive version updates.
The SPM package requires iOS 13.0 or later and Swift tools 5.9 or later.
https://github.com/stringeecom/Stringee-iOS-SDK-SPM.git
Stringee product to your app target.Swift Package Manager downloads Stringee.xcframework and its required dependencies automatically when resolving the package. For Package.swift configuration and the latest version details, see the Stringee iOS SDK SPM repository.
The simplest way to import the SDK into an iOS project is with CocoaPods. Open your project's Podfile and add this line to your app's target:
pod 'Stringee'
Then from the command line run:
pod install --repo-update
If you're new to CocoaPods, see their official documentation for info on how to create and use Podfiles.
In the "Build Settings" tab -> "Other linker flags" add "$(inherited)" flag
In the "Build Settings" tab -> "Enable bitcode" select "NO"
To add the SDK in Xcode:


Add the following libraries and frameworks to Target -> "Build Phases" -> "Link Binary With Libraries":



<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) uses Camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) uses Microphone</string>
In order to connect to Stringee Server, 3-parties authentication is required as described here: Client authentication
For testing purpose, go to Dashboard -> Tools -> Generate Access token and generates an access_token. In production, the access_token should be generated by your server. This is a sample code to generate an access token: https://github.com/stringeecom/server-samples/tree/master/access_token
#import <Stringee/Stringee.h>
In .h file
@interface ViewController : UIViewController <StringeeConnectionDelegate>
@property(strong, nonatomic) StringeeClient *stringeeClient;
@end
In .m file
- (void)requestAccessToken:(StringeeClient *)stringeeClient {
NSLog(@"requestAccessToken");
}
- (void)didConnect:(StringeeClient *)stringeeClient isReconnecting:(BOOL)isReconnecting {
NSLog(@"Successfully connected to Stringee Server, user ID: %@", stringeeClient.userId);
}
- (void)didDisConnect:(StringeeClient *)stringeeClient isReconnecting:(BOOL)isReconnecting {
NSLog(@"didDisConnect");
}
- (void)didFailWithError:(StringeeClient *)stringeeClient code:(int)code message:(NSString *)message {
NSLog(@"Failed connection to Stringee Server with error: %@", message);
}
NSString *accessToken = @"...";
self.stringeeClient = [[StringeeClient alloc] initWithConnectionDelegate:self];
[self.stringeeClient connectWithAccessToken:accessToken];
When the client connects to Stringee Server, instantiate a StringeeCall2 object and call the makeCallWithCompletionHandler method:
StringeeCall2 *stringeeCall2 = [[StringeeCall2 alloc] initWithStringeeClient:self.stringeeClient from:@"+1273065979" to:@"+1909982888"];
[stringeeCall2 makeCallWithCompletionHandler:^(BOOL status, int code, NSString * message, NSString *data){
NSLog(@"Make call result: code=%d, message: %@", code, message);
}];
The type of the outgoing call (app-to-app or app-to-phone) is decided by Your Server via the project's answer_url. Hence, you should be able to complete it independently. However, we offer an easy method for you to implement quickly:
stringeeCall2.customData = @"custom";
"custom" is a customizable text that be sent to Your Server via the project's answer_url. You can set it as: {'type': 'app-to-app'}, {'type':'app-to-phone'} or any other texts you want. Your Server will check this text to determine whether the call is app-to-app or app-to-phone.
Implement the StringeeCallDelegate protocol
#import <Stringee/Stringee.h>
@interface ViewController : UIViewController <StringeeConnectionDelegate, StringeeCall2Delegate>
@property(strong, nonatomic) StringeeClient *stringeeClient;
@end
in .m file:
//----------- StringeeCall2Delegate -->
- (void)didChangeSignalingState2:(StringeeCall2 *)stringeeCall2 signalingState:(SignalingState)signalingState reason:(NSString *)reason sipCode:(int)sipCode sipReason:(NSString *)sipReason {
NSLog(@"signalingState: %d", signalingState);
}
- (void)didChangeMediaState2:(StringeeCall2 *)stringeeCall2 mediaState:(MediaState)mediaState {
NSLog(@"mediaState: %d", mediaState);
}
- (void)didReceiveLocalStream2:(StringeeCall2 *)stringeeCall2 {
NSLog(@"didReceiveLocalStream");
}
- (void)didReceiveRemoteStream2:(StringeeCall2 *)stringeeCall2 {
NSLog(@"didReceiveRemoteStream");
}
- (void)didHandleOnAnotherDevice2:(StringeeCall2 *)stringeeCall2 signalingState:(SignalingState)signalingState reason:(NSString *)reason sipCode:(int)sipCode sipReason:(NSString *)sipReason {
NSLog(@"didAnsweredOnOtherDevice %d", signalingState);
}
//----------- StringeeCall2Delegate <--
and set delegates for stringeeCall:
stringeeCall2.delegate = self;
Implement the StringeeIncomingCallDelegate protocol
#import <Stringee/Stringee.h>
@interface ViewController : UIViewController <StringeeConnectionDelegate, StringeeCall2Delegate, StringeeIncomingCallDelegate>
@property(strong, nonatomic) StringeeClient *stringeeClient;
@end
in .m file:
- (void)incomingCallWithStringeeClient:(StringeeClient *)stringeeClient stringeeCall2:(StringeeCall2 *)stringeeCall2 {
NSLog(@"incomingCallWithStringeeClient, from: %@, to: %@", stringeeCall2.from, stringeeCall2.to);
}
and set incomingCallDelegate for stringeeClient:
self.stringeeClient.incomingCallDelegate = self;
When the client receives an incoming call
- (void)incomingCallWithStringeeClient:(StringeeClient *)stringeeClient stringeeCall2:(StringeeCall2 *)stringeeCall2 {
NSLog(@"incomingCallWithStringeeClient, from: %@, to: %@", stringeeCall2.from, stringeeCall2.to);
stringeeCall2.delegate = self;
}
Call the following method to initialize resources:
[stringeeCall2 initAnswerCall];
Call the following method to answer and start the conversation:
[stringeeCall2 answerCallWithCompletionHandler:^(BOOL status, int code, NSString *message) {
NSLog(@"%@", message);
}];
Call the following method to Hang up a call.
[stringeeCall2 hangupWithCompletionHandler:^(BOOL status, int code, NSString *message) {
NSLog(@"%@", message);
}];
Call the following method to reject a call.
[stringeeCall2 rejectWithCompletionHandler:^(BOOL status, int code, NSString *message) {
NSLog(@"%@", message);
}];
stringeeCall2.isVideoCall = YES;
- (void)didReceiveLocalStream2:(StringeeCall2 *)stringeeCall2 {
dispatch_async(dispatch_get_main_queue(), ^{
[stringeeCall2.localVideoView setFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[self.view insertSubview:stringeeCall2.localVideoView atIndex:0];
});
}
-(void) didReceiveRemoteStream2:(StringeeCall2 *)stringeeCall2 {
dispatch_async(dispatch_get_main_queue(), ^{
[stringeeCall2.remoteVideoView setFrame:CGRectMake(0, 0, self.containRemoteView.bounds.size.width, self.containRemoteView.bounds.size.height)];
[self.containRemoteView addSubview:stringeeCall2.remoteVideoView];
});
}
- (void)didChangeMediaState2:(StringeeCall2 *)stringeeCall2 mediaState:(MediaState)mediaState {
dispatch_async(dispatch_get_main_queue(), ^{
if (mediaState == MediaStateConnected) {
[[StringeeAudioManager instance] setLoudspeaker:YES];
}
});
}
You can view the full version of this sample app on GitHub: https://github.com/stringeecom/ios-sdk-samples/tree/master/CallkitSample-Call2