---
title: 3DS iOS SDK
slug: 3ds-ios-sdk
docTags: 
createdAt: 2026-06-01T13:20:13.044Z
---

## Install

The Forter3DS SDK offers flexible integration options, supporting both Swift Package Manager and CocoaPods. Choose the integration method that aligns with your project preferences and workflows add follow the steps below.

:::hint{type="warning"}
Select only one integration method and refrain from using both, as combining them may result in build conflicts.
:::

### Swift Package Manager

:::::WorkflowBlock
:::WorkflowBlockItem
In Xcode, navigate to `File` > `Swift Packages` > `Add Package Dependency...`
:::

::::WorkflowBlockItem
Enter the Forter3DS SDK repository URL

:::CodeblockTabs
Swift Package Manager

```text
https://bitbucket.org/forter-mobile/forter-ios.git
```
:::
::::

:::WorkflowBlockItem
Set the **Dependency Rule** to be `Up to Next Major Version` starting from `2.3.0`, then press **Add Package**
:::

:::WorkflowBlockItem
On the "Choose Package" screen, verify that `Forter3DS` is selected and press **Add Package**
:::
:::::

### CocoaPods

:::hint{type="success"}
Ensure that your Podfile includes the use\_frameworks! flag
:::

:::::WorkflowBlock
::::WorkflowBlockItem
In your `Podfile` add Forter3DS dependency to your target

:::CodeblockTabs
Podfile

```text
platform :ios, '11.0'
use_frameworks!

target 'YourProjectName' do
    pod 'Forter3DS', :git => 'https://bitbucket.org/forter-mobile/forter-ios.git', :tag => '2.3.0'
end
```
:::
::::

:::WorkflowBlockItem
Run `pod install`
:::
:::::

### Dependencies

Forter3DS SDK uses external libraries that are already embedded in the SDK

- **ASN1Decoder** - Certificate parsing in ASN1 structure. [MIT License](https://github.com/filom/ASN1Decoder/blob/master/LICENSE)
- **SwCrypt** - Crypto library for JWS validation (used only in iOS 10 devices) [MIT license](https://github.com/soyersoyer/SwCrypt/blob/master/LICENSE.md)
- **GMEllipticCurveCrypto** - Security framework used for Elliptic-Curve keys Crypto library. [License](https://github.com/ricmoo/GMEllipticCurveCrypto/blob/master/LICENSE.txt)

## Initialization

The Forter3DS SDK should be initialized from the **Application Delegate** during application launch. This ensures that it is loaded correctly as soon as the app becomes active.

:::::WorkflowBlock
::::WorkflowBlockItem
### Import the SDK

:::CodeblockTabs
Swift

```swift
import Forter3DS
```

Objective‑C

```objective-c
#import <Forter3DS/Forter3DS.h>
```
:::
::::

::::WorkflowBlockItem
### Setup

To initialize the `Forter3DS` SDK, you need to add the following line to your application delegate's `didFinishLaunchingWithOptions` method. This is a critical step to ensure the proper functioning of the Forter 3DS SDK within your iOS application. Make sure to replace `<your-forter-site-id>` with the site ID from the [Credentials](https://portal.forter.com/app/integration/credentials/) section of Forter Portal.

:::hint{type="info"}
In development mode, In order to present a native challenge `Forter3DS` SDK should load the test servers before calling the `setup` method, and use a dedicated test card. This is only for testing purposes and should **NOT** be used in production.
:::

:::CodeblockTabs
Swift

```swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
#if DEBUG
    Forter3DS.loadTestServers() // Only for testing
#endif
    Forter3DS.setup(siteID: "<your-forter-site-id>", customization: nil)
}
```

Objective‑C

```objective-c
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#if DEBUG
    [Forter3DS loadTestServers]; // Only for testing
#endif
    [Forter3DS setupWithSiteID:@"<your-forter-site-id>" customization:nil];
}
```
:::
::::
:::::

### Setup with a custom domain (CNAME)

:::hint{type="info"}
Available from version 2.3.0. Only needed if Forter provided you with a custom domain because your app must not call Forter's domains directly.
:::

Use this `setup` variant instead of the one above. The SDK then sends all 3DS requests (managed-order execution, verification and the 3DS Method notification) to your custom domain instead of Forter's default hosts. `thirdPartyBaseURL` is optional: pass `nil` or an empty string to use the default hosts.

The method throws `FTR3DSError.invalidThirdPartyBaseURL` (code `3007`) if the value isn't an `https` URL with a host. In that case the SDK is not set up. Read the error message from `errorDescription`.

:::CodeblockTabs
Swift

```swift
do {
    try Forter3DS.setup(siteID: "<your-forter-site-id>",
                        customization: nil,
                        thirdPartyBaseURL: "https://<your-custom-domain>") // Optional: nil uses Forter's default hosts
} catch let error as FTR3DSError {
    print("Forter3DS setup failed: \(error.errorDescription ?? "")")
} catch {
    print("Forter3DS setup failed: \(error)")
}
```

Objective‑C

```objective-c
NSError *error = nil;
BOOL ok = [Forter3DS setupWithSiteID:@"<your-forter-site-id>"
                       customization:nil
                   thirdPartyBaseURL:@"https://<your-custom-domain>" // Optional: nil uses Forter's default hosts
                               error:&error];
if (!ok) {
    NSLog(@"Forter3DS setup failed: %@", error);
}
```
:::

***

## Do Challenge if Needed

This method should be called after the managed order token is obtained from the backend (see [Order API](https://docs.forter.com/reference/order-v3)). It will display an authorization challenge if required, otherwise it will continue with the transaction.

:::hint{type="info"}
From version 2.3.0, when the card issuer requires it, the SDK first runs the issuer's 3DS Method (a short device-data collection step) in a hidden web view, for up to 15 seconds. This happens automatically and requires no code changes.
:::

**Method**

`doChallengeIfNeeded(token:vc:delegate:)`: Perform a managed order challenge if needed.

**Parameters**

- `token (String)` : The managed order token obtained from the backend.
- `vc (UIViewController)` : The view controller responsible for presenting the challenge UI.
- `delegate (FTR3DSManagedOrderDelegate)` : The delegate that will receive the challenge result.

**Example**

:::CodeblockTabs
Swift

```swift
Forter3DS.doChallengeIfNeeded(
    token: "your_managed_order_token",
    vc: YourPresentingViewController,
    delegate: self
)
```

Objective‑C

```objective-c
[Forter3DS doChallengeIfNeededWithToken:@"your_managed_order_token"
                                     vc:YourPresentingViewController
                               delegate:self];
```
:::

### Callback

The `FTR3DSManagedOrderDelegate` protocol provides a structured way to handle the completion of managed order flows. By adopting this protocol, developers can respond to the completion of managed order challenges and handle any potential errors that may arise during the process.

**Method**

`challengeCompleted(error:)`: This method is called when the managed order flow is completed, either successfully or with an error. It provides information about the status of the managed order challenge.

**Parameter**

- `error`: An optional parameter of type `Error` that indicates whether an error occurred during the managed order flow. If no error occurred, this parameter will be `nil`.

:::hint{type="info"}
From version 2.3.0, `challengeCompleted(error:)` is always called on the main thread.
:::

**Example**

:::CodeblockTabs
Swift

```swift
class PaymentViewController: UIViewController, FTR3DSManagedOrderDelegate {

    func performManagedOrderFlow() {
        // Initiating the managed order flow
    }

    // FTR3DSManagedOrderDelegate method
    func challengeCompleted(error: Error?) {
        if let error = error {
            // Handle error scenario
            print("Managed order flow completed with error: \(error.localizedDescription)")
        } else {
            // Handle success scenario
        }
    }
}
```

Objective‑C

```objective-c
@interface PaymentViewController : UIViewController <FTR3DSManagedOrderDelegate>
@end

@implementation PaymentViewController

- (void)performManagedOrderFlow {
    // Initiating the managed order flow
}

// FTR3DSManagedOrderDelegate method
- (void)challengeCompletedWithError:(NSError * _Nullable)error {
    if (error != nil) {
        NSLog(@"Managed order flow completed with error: %@", error.localizedDescription);
    } else {
        // Handle success scenario
    }
}

@end
```
:::

***

## Optional Methods

### Observe Logs

This function sets up an observer of `Forter3DS` logs. It utilizes the given NotificationCenter, observer, and selector to handle log notifications. If the service has not been initialized yet, it creates a new instance and configures it for Managed Orders. Otherwise, if the service is already initialized, it posts a log message indicating that dev logs are already initialized.

**Method**

`observeLogs(observer:selector:notificationCenter:)`: Start observing Forter3DS logs with Managed Orders context.

**Parameters**

- `notificationCenter`: The NotificationCenter to use for observing log notifications.
- `observer`: The observer object that will handle log notifications.
- `selector`: The selector method to be called on log notifications.

**Example**

:::CodeblockTabs
Swift

```swift
func startObservingLogs() {
    Forter3DS.observeLogs(
        observer: self,
        selector: #selector(handleForter3DSNotification(_:)),
        notificationCenter: NotificationCenter.default
    )
}

// MARK: Forter3DS dev logs notification

@objc func handleForter3DSNotification(_ notification: Notification) {
    guard
        let userInfo = notification.userInfo,
        let message = userInfo["message"] as? String
    else {
        return
    }
    print("[Forter dev logs]: \(message)")
}
```

Objective‑C

```objective-c
- (void)startObservingLogs {
    [Forter3DS observeLogsWithObserver:self
                              selector:@selector(handleForter3DSNotification:)
                     notificationCenter:[NSNotificationCenter defaultCenter]];
}

// MARK: Forter3DS dev logs notification

- (void)handleForter3DSNotification:(NSNotification *)notification {
    NSDictionary *userInfo = notification.userInfo;
    NSString *message = userInfo[@"message"];
    if (message != nil) {
        NSLog(@"[Forter dev logs]: %@", message);
    }
}
```
:::

### Remove Observer

This function allows you to remove the `Forter3DS` observer for Forter3DS logs. It takes the provided observer and unregisters it from the NotificationCenter associated with Forter3DS logs. The observer will no longer receive log notifications after being removed.

**Method**

`removeLogsObserver(observer:)`: Remove the Notification Observer for Forter3DS Logs.

**Parameter**

- `observer`: The observer object to be removed from log notifications.

**Example**

:::CodeblockTabs
Swift

```swift
deinit {
    Forter3DS.removeLogsObserver(observer: self)
}
```

Objective‑C

```objective-c
- (void)dealloc {
    [Forter3DS removeLogsObserver:self];
}
```
:::
