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

# Quickstart

> Get access, add the Rollup SDK to your iOS app, and run your first search, query and profile.

## Get access

<Steps>
  <Step title="Sign up for the developer dashboard">
    Go to [tryrollup.com/developers](https://www.tryrollup.com/developers) and sign in with your email. Rollup sends you a sign-in link. Your first sign-in creates a developer account that waits for Rollup to approve it. While it waits, the dashboard shows "Your access is being reviewed".
  </Step>

  <Step title="Wait for your account to be approved">
    Rollup emails you when your account is approved, or if it is not.
  </Step>

  <Step title="Create an app and accept the SDK Terms">
    Create an app with a name, your Apple Team ID (10 characters) and your app's bundle ID. Tick the box to accept the [Rollup SDK Terms](https://www.tryrollup.com/legal/sdk-terms). The app gets a publishable key that starts with `rk_live_`.
  </Step>

  <Step title="Wait for the app to be approved">
    A new app also waits for approval, and Rollup approves it only after you accept the terms. Until then, the server answers every request with the error `app_pending`. Rollup emails you when your app is approved, or if it is not.
  </Step>

  <Step title="Copy your key and setup">
    Open the app's page in the dashboard. It shows your publishable key and the setup for this app: the package URL, the Info.plist entries with your bundle ID, and the Swift code to start the SDK. The rest of this guide explains each part.
  </Step>
</Steps>

The publishable key ships inside your app, so it is not a secret. What proves a request comes from your app is App Attest, which Rollup checks against your Team ID and bundle ID.

## Set up with a coding agent

Once you have your key, you can give this prompt to your coding agent instead of following the rest of this guide by hand. Replace `rk_live_...` with your key.

<Tabs>
  <Tab title="Swift">
    <Prompt description="Add Rollup to an iOS app." actions={["copy", "cursor"]}>
      Add the Rollup SDK to this iOS app. Read [https://docs.tryrollup.com/llms-full.txt](https://docs.tryrollup.com/llms-full.txt) first and follow it.

      * Add the Swift package [https://github.com/KINT-AI/rollup-ios-sdk](https://github.com/KINT-AI/rollup-ios-sdk) (from 0.1.0) to the app target. If the project uses CocoaPods instead, add `pod 'Rollup', :podspec => 'https://raw.githubusercontent.com/KINT-AI/rollup-ios-sdk/0.1.0/Rollup.podspec'`. Set the iOS deployment target to 26.0.
      * In Info.plist, add `NSPhotoLibraryUsageDescription` (ask me for the wording), `BGTaskSchedulerPermittedIdentifiers` with `$(PRODUCT_BUNDLE_IDENTIFIER).rollup.indexing.*` and `$(PRODUCT_BUNDLE_IDENTIFIER).rollup.update`, and `processing` in `UIBackgroundModes`.
      * Add the App Attest capability.
      * When the app starts, call `Rollup.registerBackgroundTasks()` before it finishes launching, then `try Rollup.configure(publishableKey: "rk_live_...")`.
      * Call `Rollup.shared.requestPhotoAccess()` only from a screen where the person chooses to turn the feature on.
      * Before the app calls `query` or `profile`, tell the person that text derived from their photos is sent to Rollup and its model provider, and get their permission (App Store Review Guideline 5.1.2(i)).
      * Rollup's enums can gain cases: switch over them with a `default` or `@unknown default` case.
      * Build for a real iPhone with iOS 26 or later. The SDK does not run in the iOS Simulator.
    </Prompt>
  </Tab>

  <Tab title="Expo and React Native">
    <Prompt description="Add Rollup to an Expo or React Native app." actions={["copy", "cursor"]}>
      Add Rollup to this Expo app with the expo-rollup module. Read [https://docs.tryrollup.com/platforms/expo.md](https://docs.tryrollup.com/platforms/expo.md) and [https://docs.tryrollup.com/platforms/javascript-api.md](https://docs.tryrollup.com/platforms/javascript-api.md) first and follow them.

      * Run `npx expo install expo-rollup` and add the `expo-rollup` config plugin to the app config with a `photosPermission` text (ask me for the wording). The plugin sets up the iOS project: do not edit Info.plist, entitlements or the Podfile by hand.
      * Make sure `ios.bundleIdentifier` is set; it must match the app registered in the Rollup dashboard.
      * When the app starts, call `Rollup.configure('rk_live_...')`.
      * Call `Rollup.requestPhotoAccess()` only from a screen where the person chooses to turn the feature on. Use `Rollup.useIndexingState()` and `Rollup.isSearchable(state)` to know when search, query and profile can run.
      * Before the app calls `query` or `profile`, tell the person that text derived from their photos is sent to Rollup and its model provider, and get their permission (App Store Review Guideline 5.1.2(i)).
      * Handle rejections with `Rollup.isRollupError(error, code)`. On Android and the web every call rejects with `unsupportedPlatform`.
      * The module is not in Expo Go. Build a development build on a real iPhone with iOS 26 or later: `npx expo prebuild --platform ios` and `npx expo run:ios --device`. It does not run in the iOS Simulator.
    </Prompt>
  </Tab>
</Tabs>

## Add the SDK

<Tabs>
  <Tab title="Swift Package Manager">
    In Xcode, choose File, then Add Package Dependencies, and enter the package URL. Add the `Rollup` library to your app target.

    ```text theme={null}
    https://github.com/KINT-AI/rollup-ios-sdk
    ```

    Or add it to `Package.swift`:

    ```swift Package.swift theme={null}
    .package(url: "https://github.com/KINT-AI/rollup-ios-sdk", from: "0.1.0")
    ```
  </Tab>

  <Tab title="CocoaPods">
    Rollup is not on CocoaPods trunk, which stops accepting pods on December 2, 2026. Point your Podfile at Rollup's podspec:

    ```ruby Podfile theme={null}
    pod 'Rollup', :podspec => 'https://raw.githubusercontent.com/KINT-AI/rollup-ios-sdk/0.1.0/Rollup.podspec'
    ```
  </Tab>

  <Tab title="Expo and React Native">
    Install the `expo-rollup` module. Its config plugin adds the Rollup pod and configures your app target for you, so continue with [Expo and React Native](/platforms/expo) instead of the rest of this guide.

    ```sh theme={null}
    npx expo install expo-rollup
    ```
  </Tab>
</Tabs>

The framework is dynamic, signed by Rollup, and includes its own privacy manifest. Xcode embeds it in your app.

Rollup's enums, such as `IndexingState` and `RollupError.Code`, can gain cases in later versions. When you switch over one, include a `default` or `@unknown default` case.

## Configure your app target

The SDK checks these entries when you call `configure`, and throws an error that names any that are missing.

<Steps>
  <Step title="Photos usage description">
    Add `NSPhotoLibraryUsageDescription` to your Info.plist with text that tells the person why your app reads their photos.
  </Step>

  <Step title="Background task identifiers">
    Add both identifiers below to `BGTaskSchedulerPermittedIdentifiers`. The first lets indexing continue in the background after the person starts it; the second keeps the index up to date later.
  </Step>

  <Step title="Background processing mode">
    Add `processing` to `UIBackgroundModes`. In Xcode, this is the **Background processing** option of the Background Modes capability.
  </Step>

  <Step title="App Attest">
    Add the **App Attest** capability to your target. `configure` cannot check for it; without it, the device cannot register, and the first call that needs Rollup's server throws `appAttestFailed`, naming the missing capability.
  </Step>
</Steps>

```xml Info.plist theme={null}
<key>NSPhotoLibraryUsageDescription</key>
<string>Your photos help personalize the app. They stay on your iPhone.</string>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER).rollup.indexing.*</string>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER).rollup.update</string>
</array>
<key>UIBackgroundModes</key>
<array>
    <string>processing</string>
</array>
```

Development-signed builds attest in Apple's development App Attest environment, which Rollup accepts, so your real key works from your first build on a device.

## Configure the SDK

Register the background tasks and configure the SDK when your app starts. `registerBackgroundTasks` must run before your app finishes launching.

```swift MyApp.swift theme={null}
import SwiftUI
import Rollup

@main
struct MyApp: App {
    init() {
        Rollup.registerBackgroundTasks()
        do {
            try Rollup.configure(publishableKey: "rk_live_...")
        } catch {
            print("Rollup could not start: \(error)")
        }
    }

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

By default the SDK indexes the last three months of photos, screenshots and videos, and keeps adding new ones. To change what it indexes, pass `IndexOptions`. See [Index options](/guides/index-options).

## Ask for Photos access

Call `requestPhotoAccess` from a screen where the person has just chosen to turn the feature on. iOS shows its Photos prompt once.

```swift theme={null}
let access = await Rollup.shared.requestPhotoAccess()
if access == .authorized || access == .limited {
    // Indexing has started.
}
```

When the person grants access, the first index starts at once. It downloads about 225 MB of models on first run, then indexes the newest photos first. If the person leaves your app, indexing continues in the background, and iOS shows its progress. See [Background indexing](/guides/background-indexing).

With limited Photos access, the SDK indexes only the photos the person selected.

## Watch indexing

`indexing.states` reports the current state and every change after it.

```swift theme={null}
for await state in Rollup.shared.indexing.states {
    switch state {
    case .downloadingAssets(let fraction):
        print("Downloading models: \(Int(fraction * 100))%")
    case .indexing(let indexed, let total, let searchable):
        print("Indexed \(indexed) of \(total), searchable: \(searchable)")
    case .ready(let photos, _):
        print("Ready with \(photos) photos")
    case .failed(let error):
        print("Indexing failed: \(error)")
    default:
        break
    }
}
```

Search, query and profile work as soon as `state.isSearchable` is true: the index answers from the photos it holds so far, newest first, while older ones fill in.

## Search, ask and fill a profile

```swift theme={null}
let results = try await Rollup.shared.search("ramen in Tokyo last spring")
for result in results.results {
    print(result.id, result.date as Any, result.location?.city as Any)
}

let answer = try await Rollup.shared.query("Where do I eat most?")
print(answer.text)

let schema = Data("""
{
  "type": "object",
  "properties": {
    "favorite_cuisine": { "type": "string", "description": "The cuisine they eat most often" },
    "drinks_coffee": { "type": "boolean" }
  }
}
""".utf8)
let profile = try await Rollup.shared.profile(schema: schema)
print(String(decoding: profile.json, as: UTF8.self))
```

`search` runs on the iPhone. `query` and `profile` need a network connection, and each takes a few seconds to about 20 seconds.

<Warning>
  Before your app calls `query` or `profile`, it must tell the person that results of their photo index are sent to Rollup and its model provider, and get their permission. See [Privacy and App Review](/guides/privacy).
</Warning>

## Next steps

<Columns cols={2}>
  <Card title="Index options" icon="sliders-horizontal" href="/guides/index-options">
    Choose the time window, media and places.
  </Card>

  <Card title="Profile schemas" icon="braces" href="/guides/profile">
    What a schema can ask for and what comes back.
  </Card>

  <Card title="Keys and revocation" icon="key" href="/guides/keys-and-revocation">
    Rotate keys and understand what happens when access stops.
  </Card>

  <Card title="Troubleshooting" icon="life-buoy" href="/guides/troubleshooting">
    Common errors and what they mean.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.