Skip to main content

iOS Quick Start

From zero to a YES verdict on an iOS device in ten minutes.

note

Work through Prerequisites first. You will need a license key and the two Info.plist keys.


1. Add the SDK

In Xcode: File → Add Packages… and enter:

https://github.com/octetproof/octet-sdk-ios

Pin to a version rather than tracking main. Or in Package.swift:

dependencies: [
.package(url: "https://github.com/octetproof/octet-sdk-ios", from: "0.0.1-alpha")
]

Then import:

import OctetSDK

Carthage

Carthage does not propagate SwiftPM transitive dependencies. Add two lines to your Cartfile:

binary "https://raw.githubusercontent.com/octetproof/octet-sdk-ios/main/OctetSDK.json" ~> 0.0
github "apple/swift-protobuf" ~> 1.28

Carthage consumers import OctetSDKCore (not OctetSDK).


2. Add Info.plist keys

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app uses your location to verify and prove your location
to services that request it.</string>

<key>NSMotionUsageDescription</key>
<string>This app uses motion data to detect when you're stationary or
moving, which improves the confidence of location proofs.</string>

Without these, the app crashes on first launch.


3. Request location permission

The SDK refuses to start until the user grants location authorization. Request it before calling Octet.start(...):

import CoreLocation

let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()

Wait for the authorization status callback (locationManagerDidChangeAuthorization) before continuing.


4. Start the SDK

import OctetSDK

let config = OctetConfig(licenseKey: "octet_live_v4.public.…")
let sdk = try await Octet.start(config: config)

Octet.start(...) is async throws. On first launch the SDK verifies the license key locally, exchanges it for an activation token via api.octetproof.com/v1/activate, caches the token in Keychain, and brings up the proof pipeline. On subsequent launches the cached token is reused.

Any license problem throws a typed LicenseError. See License Types for the case list.


5. Ask your first question

let verdict = await sdk.loc.isWithin(
region: .country(isoCode: "US"),
atTime: Date()
)

switch verdict.result {
case .yes:
print("YES — proof attached: \(verdict.proof != nil)")
case .no:
print("NO — provable negative")
case .indeterminate:
print("INDETERMINATE — reason: \(verdict.reason)")
}

The predicate returns an OctetVerdict. The result is a trichotomy. Never treat INDETERMINATE as NO.


6. What to expect

  • On a real device, outdoors, with cellular and GPS available, isWithin(.country(isoCode: ...)) typically returns YES with an attached proof.
  • On the iOS Simulator the verdict will always be INDETERMINATE / NO_FIX with the message running on simulator — location proofs are unavailable in this environment. This is by design. The simulator has no GNSS or motion stack, and the spoof-detection pipeline blocks proof generation. Run on hardware to see the full flow.
  • On a real device, indoors, the first proof may take longer or come back at MEDIUM confidence. See Concepts: Verdicts for how confidence relates to the verdict.

7. From here