Skip to Content
SDK IntegrationSwift (iOS & macOS)

iOS / macOS SDK

Integrate TrustPin into your Apple platform application with native certificate pinning protection.

Current version: TrustPinKit 5.0.0

Platform Requirements

PlatformMinimum Version
iOS13.0+
macOS13.0+
watchOS7.0+
tvOS13.0+
Mac Catalyst13.0+
visionOS2.0+

Swift Version: 5.5+ (async/await is required)


Installation

Add TrustPin to your project in Xcode:

  1. Go to File → Add Package Dependencies
  2. Enter the repository URL:
    https://github.com/trustpin-cloud/swift.sdk
  3. Select version 5.0.0 or later (Up to Next Major).

Package.swift

For command-line projects:

dependencies: [ .package(url: "https://github.com/trustpin-cloud/swift.sdk", from: "5.0.0") ], targets: [ .target( name: "YourApp", dependencies: [ .product(name: "TrustPinKit", package: "swift.sdk") ] ) ]

CocoaPods

Add to your Podfile:

pod 'TrustPinKit', '~> 5.0'

Then run:

pod install

Quick Start

1. Get Your Credentials

Sign in to the TrustPin Dashboard  and retrieve:

  • Organization ID
  • Project ID
  • Public Key (Base64-encoded)

2. Initialize TrustPin

Ship a TrustPin-Info.plist in your app bundle and load it with TrustPinConfiguration.fromPlist(). Credentials stay out of source.

The plist must contain the following keys:

KeyTypeRequiredNotes
OrganizationIdStringYesNon-empty
ProjectIdStringYesNon-empty
PublicKeyStringYesBase64-encoded ECDSA P-256 public key
ModeStringNo"strict" (default) or "permissive", lowercase
ConfigurationURLStringNoMust be HTTPS. Overrides the default CDN endpoint

Add this to your app’s initialization (e.g., AppDelegate or @main struct):

import TrustPinKit class AppDelegate: UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Task { do { let config = try TrustPinConfiguration.fromPlist() try await TrustPin.setup(config) print("TrustPin initialized") } catch { print("TrustPin setup failed: \(error)") } } return true } }

TrustPinConfiguration.fromPlist() throws TrustPinErrors.invalidProjectConfig if any required key is missing or malformed.

Per-environment plists

Point the factory at a different bundle or filename to ship different credentials per scheme:

#if DEBUG let config = try TrustPinConfiguration.fromPlist(fileName: "TrustPin-Info-Debug.plist") #else let config = try TrustPinConfiguration.fromPlist(fileName: "TrustPin-Info.plist") #endif try await TrustPin.setup(config)

Integration Approaches

TrustPin offers three integration methods:

ApproachBest ForSetup Complexity
URLSessionDelegate (Recommended)Most applications, precise control🟢 Low
System-Wide URLProtocolThird-party library protection, legacy code🟡 Medium
Helper MethodsOne-off requests, explicit control🟠 High

Bind a URLSession to a TrustPin-backed delegate produced by the SDK:

import TrustPinKit class NetworkManager { private lazy var session: URLSession = { let delegate = TrustPin.makeURLSessionDelegate() return URLSession( configuration: .default, delegate: delegate, delegateQueue: nil ) }() func fetchData() async throws -> Data { let url = URL(string: "https://api.example.com/data")! let (data, _) = try await session.data(from: url) return data } }

System-Wide URLProtocol

Register TrustPinURLProtocol to apply pinning to every request that goes through the default URL Loading System — useful when third-party libraries don’t expose a URLSession you control.

You can either register automatically during setup, or register/unregister manually:

let config = try TrustPinConfiguration.fromPlist() try await TrustPin.setup(config, autoRegisterURLProtocol: true) // Or manage registration explicitly: TrustPin.registerURLProtocol() TrustPin.unregisterURLProtocol()

Helper Methods

TrustPinURLProtocol exposes convenience helpers for individual requests:

let (data, _) = try await TrustPinURLProtocol.data(from: url) let (fileURL, _) = try await TrustPinURLProtocol.download(for: request)

Manual Verification

For custom transports or one-off checks, validate a domain/certificate pair directly:

try await TrustPin.verify( domain: "api.example.com", certificate: pemEncodedCertificate )

Named Instances (Multi-Tenant)

If your app talks to multiple TrustPin projects (for example, separate consumer and admin backends), ship one plist per project and create independent instances:

let customerConfig = try TrustPinConfiguration.fromPlist(fileName: "TrustPin-Customer.plist") let customerApi = try TrustPin.instance(id: "customer-api") try await customerApi.setup(customerConfig) let adminConfig = try TrustPinConfiguration.fromPlist(fileName: "TrustPin-Admin.plist") let adminApi = try TrustPin.instance(id: "admin-api") try await adminApi.setup(adminConfig)

The id must be non-empty and not equal to "default"; otherwise TrustPinErrors.invalidProjectConfig is thrown. Repeated calls with the same id return the same instance.


Logging

Set the desired verbosity before calling setup() to capture initialization logs:

await TrustPin.set(logLevel: .debug)

Available levels: .none, .error, .info, .debug.


Error Handling

All SDK errors are cases of TrustPinErrors:

do { try await TrustPin.setup(config) } catch TrustPinErrors.invalidProjectConfig { // Bad credentials or invalid configuration } catch TrustPinErrors.errorFetchingPinningInfo { // Network failure while loading the configuration } catch TrustPinErrors.configurationValidationFailed { // JWS signature didn't verify against the project's public key } catch TrustPinErrors.domainNotRegistered { // Strict mode and the host isn't in the configuration } catch TrustPinErrors.pinsMismatch { // Server certificate doesn't match any active pin } catch TrustPinErrors.allPinsExpired { // Configuration is stale — rotate pins in the dashboard } catch TrustPinErrors.invalidServerCert { // Server returned an unparseable certificate }

Best Practices

Setup & Initialization

  1. Call TrustPin.setup() once during app launch. Subsequent calls return immediately.
  2. Set the log level before setup() to capture initialization output.
  3. Handle setup errors gracefully — don’t block app launch.
  4. Don’t call setup() concurrently from multiple tasks for the same instance.

Security

  1. Use .strict mode in production.
  2. Prefer SPKI pinning; rotate pins in the dashboard before they expire.
  3. Monitor pin validation failures via logging or analytics.
  4. Keep credentials outside source control — TrustPinConfiguration.fromPlist() reads from a bundled plist.
  5. Use HTTPS for all pinned domains.

Performance

  1. Reuse URLSession instances rather than creating a new one per request.
  2. Configuration is cached for 10 minutes; the SDK refreshes automatically.
  3. Use .error or .none log levels in production.

Complete Documentation

For the full API reference, including every method signature, integration examples (Alamofire, third-party clients), and advanced configuration, visit:

TrustPinKit API Reference 


Resources