Skip to content

Getting Started

iOS Requirements:

  • iOS 15.0+
  • Xcode 15.0+

Permissions Required: The SDK needs no entitlements and adds no privacy prompt to your app. It uses no location, camera, microphone or contacts API, and the Secure Enclave keys it creates are not gated on biometry, so nothing it does raises a Face ID or passcode dialog.

It does need the Info.plist keys below. alphyn-cli integrate merges them for you; add them by hand only when you integrate without the CLI.

<!-- Background Task Scheduler Permitted Identifiers -->
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.byterialab.backgroundcheck</string>
</array>
<!-- Background Modes -->
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
<!-- URL schemes the jailbreak detector probes -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>cydia</string>
<string>sileo</string>
<string>zbra</string>
<string>filza</string>
<string>undecimus</string>
<string>installer</string>
<string>taig</string>
<string>dopamine</string>
<string>trollstore</string>
<string>trollstorehelper</string>
</array>
<!-- Network Security Configuration (App Transport Security) -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<key>alphyn-attestation-api.byterialab.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>

Important Notes for Info.plist:

  • The BGTaskSchedulerPermittedIdentifiers key is required and must include com.byterialab.backgroundcheck.
  • The fetch background mode is required for BGAppRefreshTask to allow background security checks.
  • The LSApplicationQueriesSchemes list is what the jailbreak detector probes. canOpenURL returns false for any scheme the host app has not declared, so a shortened list silently narrows detection and produces no error.
  • The NSAppTransportSecurity exception is required; the SDK cannot reach the backend without it. The attestation host presents a certificate from a private CA (CN=Byteria Root CA) that the system trust store does not carry, so without the exception the connection is refused inside ATS with TLS error -9802 and the SDK’s own certificate check is never reached, so init fails at launch. NSExceptionAllowsInsecureHTTPLoads is the key that carries the connection past ATS; the SDK then validates the chain itself against a root anchor bundled in Alphyn.framework, and that pinning stays the effective transport control. The exception is scoped to that one domain and weakens nothing else.
  • After adding these configurations, clean and rebuild your project. If you encounter registration errors related to background tasks, delete the app from your device/simulator and reinstall it.

Call AlphynSDK.register() synchronously in application(_:didFinishLaunchingWithOptions:) - it registers the SDK’s background tasks with iOS and cannot be deferred:

import Alphyn
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
do {
try AlphynSDK.register()
} catch {
print("AlphynSDK.register() failed: \(error.localizedDescription)")
}
return true
}
}

There are three ways to add the framework. Pick one; the Info.plist keys and the register() call above, and Initialize the SDK below, are the same whichever you choose.

  • Option 1, the Alphyn CLI: one command wires everything. Recommended.
  • Option 2, from the registry by hand: you add a Swift Package binaryTarget yourself and the registry serves the framework. Nothing is committed into your repo.
  • Option 3, offline: an Alphyn.xcframework you download and embed, for build machines that cannot reach the registry.
Section titled “Option 1: Install with the Alphyn CLI (recommended)”
Terminal window
alphyn-cli integrate --ios-api-key <IOS_APP_KEY>

It generates a local Swift package that resolves Alphyn.xcframework from the Alphyn package registry as a checksum-pinned binaryTarget, wires it into your Xcode project, merges the required Info.plist keys, adds the launch hook, and installs the archive post-action that registers each build. Swift Package Manager authenticates to the registry with your app API key through ~/.netrc; see SDK Registry Access and CLI: iOS.

For the development loop, pin your app’s debug hash from the dashboard under App Details. An iOS app’s hash changes on every build and only archives register, so debug and simulator builds cannot initialize the SDK without it:

Terminal window
alphyn-cli integrate --ios-api-key <IOS_APP_KEY> --ios-debug-hash <64-HEX>

Option 2: Install from the registry, by hand (no CLI)

Section titled “Option 2: Install from the registry, by hand (no CLI)”

Add Alphyn.xcframework as a checksum-pinned Swift Package binaryTarget yourself and let the registry serve it. Nothing is downloaded into your repo.

Before you start: register your iOS app and generate its API key (see How to Register Your App).

Step 1. Let Swift Package Manager authenticate to the registry. Add one line to your ~/.netrc (the login is the literal x, the password is your app API key); see SDK Registry Access:

machine packages.byterialab.com login x password <YOUR_APP_API_KEY>

Step 2. Ask the registry for the latest framework. One call returns the version, the zip URL, and the checksum (the user is x, the password is your key):

Terminal window
curl -u "x:<YOUR_APP_API_KEY>" https://packages.byterialab.com/spm/latest
# -> {"version":"...","url":"https://packages.byterialab.com/spm/<version>/Alphyn.xcframework.zip","checksum":"<sha256>"}

Step 3. Declare the binary target. Put a local Package.swift in your project with the url and checksum from Step 2:

Package.swift
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "AlphynLocal",
products: [.library(name: "Alphyn", targets: ["Alphyn"])],
targets: [
.binaryTarget(
name: "Alphyn",
url: "https://packages.byterialab.com/spm/<version>/Alphyn.xcframework.zip",
checksum: "<checksum from /spm/latest>"
)
]
)

Step 4. Add the package to Xcode. In Xcode: File -> Add Package Dependencies -> Add Local, select the folder that holds this Package.swift, and add the Alphyn product to your app target.

Expected result: Xcode resolves Alphyn and verifies the download against your checksum. If it cannot authenticate, recheck the ~/.netrc line in Step 1.

Then add the Info.plist keys and the register() call above, Initialize the SDK below, and register your builds with the Xcode archive post-action.

Option 3: Install offline (embedded XCFramework)

Section titled “Option 3: Install offline (embedded XCFramework)”

If your build cannot reach the registry, embed the self-contained Alphyn.xcframework directly. It carries the native inside it and needs no registry access at build time.

Step 1. Download Alphyn.xcframework from your app’s SDK Downloads page in the Alphyn dashboard. The download is gated by your app API key.

Step 2. Drag Alphyn.xcframework into your Xcode project’s “Frameworks, Libraries, and Embedded Content” section, and set it to Embed & Sign.

Step 3. Register each build. Without the archive post-action the CLI installs, a build is never enrolled and the app fails attestation at runtime with no build-time error. See Register via Xcode post-action.

Basic Integration Example:

import SwiftUI
import Alphyn
// It is highly recommended to initialize AlphynSDK in your App's entry point
// (e.g., in your App.swift struct or AppDelegate) for best performance
// and consistent lifecycle management.
// Example (in your App.swift):
// @main
// struct YourApp: App {
// @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
// var body: some Scene {
// WindowGroup {
// ContentView()
// }
// }
// }
//
// In your AppDelegate.swift:
// class AppDelegate: UIResponder, UIApplicationDelegate {
// func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// // 1. Register Alphyn background tasks (synchronous, must run at launch).
// do {
// try AlphynSDK.register()
// } catch {
// print("AlphynSDK.register() failed: \(error.localizedDescription)")
// }
// // 2. Initialize the SDK (async). `initialize` is `async throws` - call it with `try await`.
// Task {
// do {
// try await AlphynSDK.initialize(interval: 45) // seconds, must be > 8
// } catch {
// print("AlphynSDK initialization failed: \(error)")
// }
// }
// return true
// }
// }
final class QuickStartSecurityListener: AlphynSecurityListener {
private let onThreatDetectedAction: (String) -> Void
init(onThreatDetectedAction: @escaping (String) -> Void) {
self.onThreatDetectedAction = onThreatDetectedAction
}
func onSuccess(_ result: AlphynCallbackResult) {
print("Alphyn Success: \(result.message)")
if result.originalEventType == .initComplete {
print("AlphynSDK initialized successfully")
}
}
func onFailure(_ result: AlphynCallbackResult) {
print("Alphyn Failure: \(result.message)")
}
func onThreatDetected(_ result: AlphynCallbackResult) {
print("Alphyn Threat detected: \(result.message)")
onThreatDetectedAction(result.message)
}
}
struct ContentView: View {
@State private var showingThreatAlert = false
@State private var threatMessage: String = ""
@State private var securityListener: QuickStartSecurityListener?
var body: some View {
VStack {
Text("Alphyn SDK Integration Example")
.font(.largeTitle)
.padding()
Text("App is running. Check console for Alphyn SDK events.")
.padding()
}
.onAppear {
// Initialize SDK (if not done in AppDelegate).
// For production apps, initialization should ideally happen once at the app's entry point.
if !AlphynSDK.isInitialized() {
Task {
do {
try await AlphynSDK.initialize(interval: 45)
print("AlphynSDK initialized in ContentView.onAppear")
} catch {
print("AlphynSDK initialization failed: \(error)")
}
}
}
// Create and add the security listener when the view appears
securityListener = QuickStartSecurityListener { message in
self.threatMessage = message
self.showingThreatAlert = true
}
if let listener = securityListener {
AlphynSDK.addSecurityListener(listener)
}
}
.onDisappear {
// Remove the security listener when the view disappears
if let listener = securityListener {
AlphynSDK.removeSecurityListener(listener)
self.securityListener = nil
}
}
.alert("Security Alert", isPresented: $showingThreatAlert) {
Button("OK") {
threatMessage = ""
showingThreatAlert = false
}
} message: {
Text(threatMessage.isEmpty ? "A security threat has been detected." : threatMessage)
}
}
}