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

# Configuring the Candid iOS SDK

> Set up the Candid SDK once at app launch with your API key, reward, recording duration, step timings, and appearance before calling any other SDK method.

Configure the Candid SDK once, before you call any other SDK method, by passing a `Candid.Configuration` value to `Candid.configure(_:)`. The best place to do this is early in your app's lifecycle, such as in `AppDelegate.application(_:didFinishLaunchingWithOptions:)` or at the top level of your `@main` `App` struct. Every property on `Configuration` has a sensible default, so you only need to supply the values you want to override.

```swift theme={null}
import CandidSDK

Candid.configure(
    Candid.Configuration(
        apiKey: "cpk_your_project_key",
        reward: nil,
        recordingDuration: 480,
        stepTimings: [
            .openQuestion: Candid.Configuration.StepTiming(canSkipAfter: 5, promptEvery: 15),
            .action: Candid.Configuration.StepTiming(canSkipAfter: 30, promptEvery: 0)
        ],
        appearance: Candid.Appearance(
            primaryColor: "#4F46E5",
            font: .system(.rounded)
        )
    )
)
```

To identify the current participant, call `Candid.setUserId(_:)` separately, at any time before or after `configure(_:)`:

```swift theme={null}
Candid.setUserId("user_42")
```

<Note>
  Call `Candid.configure(_:)` before `Candid.register(trigger:)` or any other SDK entry point. Calling SDK methods before configuration results in undefined behavior.
</Note>

## Configuration properties

<ParamField path="apiKey" type="String?" required>
  Your Candid project API key. Keys follow the format `cpk_...` and are found in the Candid dashboard under **Project → API Keys**. Omitting this value prevents the SDK from uploading recordings.
</ParamField>

<ParamField path="reward" type="Reward?">
  An optional reward unlocked after the session uploads successfully. Defaults to `nil` (no reward). See the [Rewards](/configuration/rewards) page for configuration details.
</ParamField>

<ParamField path="recordingDuration" type="TimeInterval">
  Maximum number of seconds to record before the session automatically ends. Defaults to `600` (10 minutes). The SDK stops recording and finalizes the streaming upload when this limit is reached, even if the participant has not finished all steps.
</ParamField>

<ParamField path="stepTimings" type="[StepType: StepTiming]">
  Defines how long a participant must wait before they can skip each step type. See [Step timings](#step-timings) below.
</ParamField>

<ParamField path="appearance" type="Appearance">
  Overrides the primary color, font, and widget position used throughout the Candid UI. See the [Appearance](/configuration/appearance) page for full details.
</ParamField>

## Participant identifier

The user id is not part of the configuration. Set it with `Candid.setUserId(_:)`, for example once the user logs in, and clear it with `nil` on sign-out. Pass any stable, non-PII string, such as your internal user ID, to correlate sessions in the Candid dashboard. When no user id is set, requests are sent anonymously and once-per-user study presentation is tracked locally per install.

***

## Step timings

`stepTimings` is a dictionary from step type to `StepTiming`. There are two step types, `.openQuestion` and `.action`. Each `StepTiming` has two fields: `canSkipAfter` (seconds until the skip button appears) and `promptEvery` (seconds between re-prompt nudges; `0` disables nudging). Step types without an entry keep their default timing.

```swift theme={null}
Candid.Configuration(
    stepTimings: [
        .openQuestion: Candid.Configuration.StepTiming(canSkipAfter: 1, promptEvery: 15),
        .action: Candid.Configuration.StepTiming(canSkipAfter: 30, promptEvery: 0)
    ]
)
```

<ParamField path=".openQuestion" type="StepTiming">
  Timing for open-ended question steps. The default allows skipping after `1` second and re-prompts the participant every `15` seconds.
</ParamField>

<ParamField path=".action" type="StepTiming">
  Timing for action (task) steps. The default allows skipping after `30` seconds and never re-prompts (`promptEvery: 0`).
</ParamField>

<Tip>
  Increase the `.openQuestion` `canSkipAfter` if participants are skipping before they have a chance to read the question. Increase the `.action` `canSkipAfter` for longer, more complex tasks.
</Tip>
