# iOS Quick Start

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

:::note

Work through [Prerequisites](/docs/v2.0/getting-started/prerequisites/) first. You will need a registered app (or a sandbox token for local development) and the two `Info.plist` keys.

:::

---

## 1. Add the SDK

### Swift Package Manager (recommended)

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`:

```swift
dependencies: [
    .package(url: "https://github.com/octetproof/octet-sdk-ios", exact: "2.0.0")
]
```

Pin 2.0.0 or later. 2.0 is a major release. If you are on 1.x, read [Migrating from 1.x](/docs/v2.0/getting-started/migrating-from-1x/) first.

Then import:

```swift
import OctetSDK
```

### Carthage

Carthage does not propagate SwiftPM transitive dependencies, but OctetSDK declares none. Add one line to your `Cartfile`:

```
binary "https://raw.githubusercontent.com/octetproof/octet-sdk-ios/main/OctetSDK.json" >= 2.0.0
```

The module name is `OctetSDK`.

---

## 2. Add `Info.plist` keys

```xml
<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.

The xcframework also bundles a privacy manifest (`PrivacyInfo.xcprivacy`) declaring the data types it handles (location, device identifier, aggregate usage counters) and its required-reason API use. Xcode folds this into your app's privacy report at build time.

---

## 3. Request location permission

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

```swift
import CoreLocation

let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
```

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

---

## 4. Start the SDK

`Octet.start(...)` bootstraps the license by attesting the app with Apple App Attest, then brings up the proof pipeline. On a real device with the App Attest capability enabled (see [Prerequisites](/docs/v2.0/getting-started/prerequisites/)), no key or token is needed.

```swift
import OctetSDK

let config = OctetConfig(licenseKey: "")   // required by the type, ignored by start
let sdk = try await Octet.start(config: config)
```

On a **simulator** or a locally built debug build, there is no hardware attestation. Mint a sandbox bypass token (see [Prerequisites](/docs/v2.0/getting-started/prerequisites/)) and pass it:

```swift
let config = OctetConfig(licenseKey: "", sandboxBypassToken: "octet_sbx_...")
```

`Octet.start(...)` is `async throws`. Any license or bootstrap problem throws a typed `LicenseError`. See [License Types](/docs/v2.0/api-reference/license-types/) for the case list, and [Attested bootstrap](/docs/v2.0/concepts/attested-bootstrap/) for the handshake.

---

## 5. Ask your first question

```swift
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`](/docs/v2.0/api-reference/octet-verdict/). Never treat `INDETERMINATE` as `NO`.

---

## 6. Close when done

When your proof flow ends, release the session and stop background work:

```swift
await sdk.close()
```

See [Session Lifecycle](/docs/v2.0/concepts/lifecycle/) for why this matters.

---

## 7. 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. 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](/docs/v2.0/concepts/verdicts/).

---

## 8. From here

- The [OctetSample sample app](/docs/v2.0/samples/ios-toy-app/) exercises this whole flow.
- [On-device Verification](/docs/v2.0/concepts/on-device-verification/) checks a proof with [`Octet.verify`](/docs/v2.0/api-reference/octet-verify/), offline.
- [Proof Binding](/docs/v2.0/concepts/proof-binding/) ties a proof to a login or a decision, and `forceFresh` mints one on demand.
- [Verifying Proofs](/docs/v2.0/concepts/verifying-proofs/) and the [Verifier Quick Start](/docs/v2.0/getting-started/verifier-quickstart/) show independent verification.
- [What's new in 2.0](/docs/v2.0/whats-new/) lists the full release.
