> ## 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.

# Rewarding Users After Completing a Test

> Configure a reward to unlock for participants after they finish all steps and their recording uploads successfully to Candid.

A reward is optional and the SDK unlocks it after a participant finishes every step in the study **and** the recording has uploaded successfully to Candid. This sequencing is intentional: the reward is only granted once you have a confirmed upload, so you never hand out rewards for incomplete or failed sessions. You define what the reward is and how to fulfill it, Candid handles the timing and the fulfillment UI.

Configure a reward by creating a `Candid.Reward` value and passing it to `Candid.Configuration(reward:)`.

***

## Reward properties

<ParamField path="calloutText" type="String" required>
  The text shown on the reward callout, inviting the participant to complete the test to get their reward. Write something specific so participants know what they are getting, e.g. `"Complete the test to unlock your free 7-day trial."`.
</ParamField>

<ParamField path="calloutImageSystemName" default="gift.fill" type="String">
  The SF Symbol name displayed as the reward icon on the callout. Defaults to `"gift.fill"`. Use any symbol from the [SF Symbols](https://developer.apple.com/sf-symbols/) library that matches the nature of your reward.
</ParamField>

<ParamField path="successCompletion" type="@MainActor @Sendable () async throws -> RewardSuccessMessage" required>
  An async closure called on the main actor once the participant completed every step and the recording uploaded. Fulfill the reward here (e.g. call your backend), then return a `RewardSuccessMessage` value to tell the SDK how to proceed.
</ParamField>

***

## Success outcomes

After your `successCompletion` closure fulfills the reward, return a `RewardSuccessMessage` value to tell Candid what to display next.

<ParamField path=".default(message:)" type="RewardSuccessMessage">
  Candid displays its built-in thank-you screen. When you supply a `message`, it is shown as the subtitle; return `.default()` to use Candid's default thank-you copy. Use this when you want a consistent, low-effort end screen without any extra work in your app.

  ```swift theme={null}
  return .default(message: "Your 7-day trial is now active. Enjoy!")
  ```
</ParamField>

<ParamField path=".hostHandled" type="RewardSuccessMessage">
  Candid dismisses its UI and hands control back to your app. Use this when you want to present your own confirmation screen, navigate to a specific part of your app, or trigger an in-app purchase flow.

  ```swift theme={null}
  return .hostHandled
  ```
</ParamField>

***

## Complete example

The example below unlocks a premium subscription trial after the participant completes the test. The `successCompletion` closure calls your backend, activates the trial, and returns `.default` so Candid shows a confirmation message.

```swift theme={null}
import CandidSDK

let trialReward = Candid.Reward(
    calloutText: "As a thank-you, complete the test to claim your free 7-day premium trial.",
    calloutImageSystemName: "star.fill",
    successCompletion: {
        // Activate the trial on your backend, then let Candid
        // show a built-in confirmation screen
        return .default(
            message: "Your 7-day trial is now active. Enjoy the full experience!"
        )
    }
)

Candid.configure(
    Candid.Configuration(
        apiKey: "cpk_your_project_key",
        reward: trialReward
    )
)
```

<Tip>
  If activating the reward requires a network call, perform it inside your `successCompletion` closure before returning. The Candid screen stays visible until the closure returns, so participants always see a response, never a blank screen.
</Tip>

<Warning>
  Do not call `Candid.register(trigger:)` from inside the `successCompletion` closure. Starting a new study while the reward screen is still presented leads to undefined navigation behavior.
</Warning>
