> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trypillow.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting started

> Install the Pillow SDK and present your first study on iOS

Get the Pillow SDK running in your iOS app in a few minutes.

## Prerequisites

* iOS 16.0+
* A **publishable API key**. See [Apps and API keys](/sdk/apps-and-keys) to create one.
* A **study** set to live mode. Copy its ID from the **Integration** tab.

## Installation

In Xcode, go to **File > Add Package Dependencies** and enter the repository URL:

```
https://github.com/trypillow/pillow-ios-sdk.git
```

Select version `0.1.6` or later, then add `PillowSDK` to your target.

You only need to add the Swift Package and `import PillowSDK` in your app code. Do not copy any SDK source files into your project.

## Initialize the SDK

Call `initialize()` once at app startup, typically in your `AppDelegate` or app entry point:

```swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
import PillowSDK

PillowSDK.shared.initialize(publishableKey: "pk_live_...")
```

<Warning>
  Initialize the SDK once during app startup and avoid calling it repeatedly from view code.
</Warning>

## Present your first study

Show a study to the user by calling `present(study:)`:

```swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
PillowSDK.shared.present(
    study: PillowStudy(id: "your-study-id-here")
)
```

The study opens as a modal overlay. The user can complete the interview and dismiss it when done.

## Enable microphone (optional)

If your study uses voice input, add the microphone usage description to your `Info.plist`:

```xml theme={"theme":{"light":"github-light","dark":"github-dark"}}
<key>NSMicrophoneUsageDescription</key>
<string>This app uses the microphone for voice-based research interviews.</string>
```

<Info>
  If you skip this step, the microphone button won't appear in studies that support voice input.
</Info>

## Full example (SwiftUI)

```swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
import SwiftUI
import PillowSDK

@main
struct MyApp: App {
    init() {
        PillowSDK.shared.initialize(publishableKey: "pk_live_...")
        PillowSDK.shared.setExternalId(externalId: "user_123")
        PillowSDK.shared.setUserProperty(key: "plan", stringValue: "pro")
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    @State private var studyCoordinator: StudyPresentationCoordinator?
    @State private var statusMessage = "Ready"

    var body: some View {
        VStack(spacing: 16) {
            Text(statusMessage)

            Button("Start feedback") {
                presentStudy()
            }
        }
    }

    private func presentStudy() {
        let coordinator = StudyPresentationCoordinator(
            onPresented: { study in
                statusMessage = "Study \(study.id) is on screen"
            },
            onFinished: { study in
                statusMessage = "Study \(study.id) finished"
                studyCoordinator = nil
            },
            onFailed: { study, error in
                statusMessage = "Failed to load \(study.id): \(error.localizedDescription)"
                studyCoordinator = nil
            }
        )

        studyCoordinator = coordinator
        PillowSDK.shared.present(
            study: PillowStudy(id: "your-study-id-here"),
            delegate: coordinator
        )
    }
}

private final class StudyPresentationCoordinator: PillowStudyDelegate {
    private let onPresented: (PillowStudy) -> Void
    private let onFinished: (PillowStudy) -> Void
    private let onFailed: (PillowStudy, Error) -> Void

    init(
        onPresented: @escaping (PillowStudy) -> Void = { _ in },
        onFinished: @escaping (PillowStudy) -> Void = { _ in },
        onFailed: @escaping (PillowStudy, Error) -> Void = { _, _ in }
    ) {
        self.onPresented = onPresented
        self.onFinished = onFinished
        self.onFailed = onFailed
    }

    func studyDidPresent(_ study: PillowStudy) {
        Task { @MainActor in
            onPresented(study)
        }
    }

    func studyDidFinish(_ study: PillowStudy) {
        Task { @MainActor in
            onFinished(study)
        }
    }

    func studyDidFailToLoad(_ study: PillowStudy, error: Error) {
        Task { @MainActor in
            onFailed(study, error)
        }
    }
}
```

If you do not need lifecycle callbacks, you can call `present(study:)` directly without a delegate.

## Full example (UIKit)

```swift theme={"theme":{"light":"github-light","dark":"github-dark"}}
import UIKit
import PillowSDK

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        PillowSDK.shared.initialize(publishableKey: "pk_live_...")
        PillowSDK.shared.setExternalId(externalId: "user_123")
    }

    @IBAction func startStudy() {
        PillowSDK.shared.present(
            study: PillowStudy(id: "your-study-id-here")
        )
    }
}
```

## What's next

<CardGroup cols={3}>
  <Card title="Identify users" icon="user" href="/sdk/ios/identification">
    Set external IDs and user properties.
  </Card>

  <Card title="Present studies" icon="presentation" href="/sdk/ios/studies">
    Control when and how studies appear.
  </Card>

  <Card title="Session management" icon="refresh-cw" href="/sdk/ios/session-management">
    Handle logout and session lifecycle.
  </Card>
</CardGroup>
