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

# Reward Placements

> Reward a user in your iOS, Android, React Native, or Flutter app the moment they finish something worth celebrating, with copy you set per call.

Reward a user the moment they accomplish something: a completed purchase, a kept streak, a cleared milestone. Encore presents a reward sheet with premium brand offers (a real perk a brand funds to acquire customers), and it costs you nothing to give. This is the [Reward Users](/publishers/use-cases/post-action-reward) use case; *why* and *when* to use it live on that page.

<Note>
  Requires **iOS SDK 2.0.0**, **Android SDK 2.0.2**, **React Native SDK 2.0.2**, or **Flutter SDK 2.0.1**. There is no setup step before this guide: your app is granted its use cases when the app is created, and a reward placement needs no subscription product and no purchase controller.
</Note>

## The complete pattern

Identify the user, then present the placement at the moment your app detects the achievement. Select the `rewardUsers` use case, and set `headline` and `subheadline` to name the moment:

<CodeGroup>
  ```swift iOS theme={null}
  import Encore

  @MainActor
  func celebrateStreak(customerId: String) async {
      Encore.shared.identify(userId: customerId) // identity powers attribution

      let result = await Encore.shared.placement("streak_day_7")
          .useCase(.rewardUsers)
          .headline("Nice work, Sam!")                      // optional
          .subheadline("That is your fifth week running")   // optional
          .show()

      if let claim = result.claim {
          // The user claimed an offer. Keep claim.transactionId; it carries the attribution.
          if let transactionId = claim.transactionId { persistClaim(transactionId) }
      }
      // Every other result: carry on with your own celebration screen.
  }
  ```

  ```kotlin Android theme={null}
  import androidx.lifecycle.LifecycleCoroutineScope
  import com.encorekit.encore.Encore
  import com.encorekit.encore.UseCase
  import kotlinx.coroutines.launch

  fun celebrateStreak(scope: LifecycleCoroutineScope, customerId: String) {
      Encore.shared.identify(userId = customerId) // identity powers attribution

      scope.launch {
          val result = Encore.placement("streak_day_7")
              .useCase(UseCase.REWARD_USERS)
              .headline("Nice work, Sam!")                      // optional
              .subheadline("That is your fifth week running")   // optional
              .show()

          result.claim?.let { claim ->
              // The user claimed an offer. Keep claim.transactionId; it carries the attribution.
              claim.transactionId?.let(::persistClaim)
          }
          // Every other result: carry on with your own celebration screen.
      }
  }
  ```

  ```tsx React Native theme={null}
  import Encore, { UseCase } from '@encorekit/react-native';

  async function celebrateStreak(customerId: string) {
    await Encore.identify(customerId); // identity powers attribution

    const result = await Encore.placement('streak_day_7')
      .useCase(UseCase.rewardUsers)
      .headline('Nice work, Sam!')                      // optional
      .subheadline('That is your fifth week running')   // optional
      .show();

    if (result.status === 'presented' && result.claim) {
      // The user claimed an offer. Keep claim.transactionId; it carries the attribution.
      if (result.claim.transactionId) persistClaim(result.claim.transactionId);
    }
    // Every other result: carry on with your own celebration screen.
  }
  ```

  ```dart Flutter theme={null}
  import 'package:encore_flutter/encore_flutter.dart';

  Future<void> celebrateStreak(String customerId) async {
    await Encore.shared.identify(userId: customerId); // identity powers attribution

    final result = await Encore.placement('streak_day_7')
        .useCase(EncoreUseCase.rewardUsers)
        .headline('Nice work, Sam!')                      // optional
        .subheadline('That is your fifth week running')   // optional
        .show();

    final claim = result.claim;
    if (claim != null) {
      // The user claimed an offer. Keep claim.transactionId; it carries the attribution.
      final transactionId = claim.transactionId;
      if (transactionId != null) persistClaim(transactionId);
    }
    // Every other result: carry on with your own celebration screen.
  }
  ```
</CodeGroup>

Contracts: `placement()` for [iOS](/publishers/ios/sdk-reference/placement), [Android](/publishers/android/sdk-reference/placement), [React Native](/publishers/react-native/sdk-reference/placement), and [Flutter](/publishers/flutter/sdk-reference/placement) · `PresentationResult` for [iOS](/publishers/ios/sdk-reference/presentation-result), [Android](/publishers/android/sdk-reference/presentation-result), [React Native](/publishers/react-native/sdk-reference/presentation-result), and [Flutter](/publishers/flutter/sdk-reference/presentation-result).

`show()` never throws (on React Native, its promise never rejects) and resolves exactly once. On iOS call it from a main-actor context; on Android it is a suspend function, so call it from a coroutine such as `lifecycleScope`; on React Native and Flutter, await it. iOS and Android also take a callback form for call sites that can't await: `show(resume:)` on iOS and `show(onResult:)` on Android.

A reward placement is claim-only: it runs no in-app purchase, so your purchase controller is never called.

## Where the copy comes from

`headline` and `subheadline` take the finished string for one presentation, and Encore never translates it, so localize it yourself. Pass nothing and the sheet still renders, with the copy Encore resolved for your app or the copy shipped with the screen. The full chain is on [Where the copy comes from](/publishers/use-cases/post-action-reward#where-the-copy-comes-from).

## Read the result

`result.claim` is the offer the user claimed, or empty when they didn't claim one. On React Native it exists only on a presented result, so check `result.status` first. It means the user tapped through to the brand, not that they finished the offer. Keep `claim.transactionId` when it is present; it carries the attribution.

When no sheet appeared, the result says why. No offers matching this user, an error (which arrives as a value on the result), and `useCaseUnavailable` (`use_case_unavailable` on React Native) are the common reasons. `useCaseUnavailable` means nothing resolved for this use case, which includes a user in the holdout group of an Encore sheet experiment that shows its holdout group no sheet. A reward placement never returns `experimentControl` (`experiment_control` on React Native); that reason belongs to the Reduce Churn control cohort. Treat each of these as a normal outcome for a reward moment: show your own celebration without the offer and carry on.

## Gotchas

* **You pass the finished string.** There is no streak-count or milestone-count parameter; Encore never assembles a sentence out of a count.
* **A blank override is not an override.** An empty or whitespace-only value falls through to the next source rather than clearing the line. To show less, omit the call.
* **A claim is not a conversion.** The bounty is earned only when the brand-side completion is verified on Encore's servers. Never pay out or grant access on a claim alone; the [offer\_completed webhook](/publishers/offers-api/guides/receive-completion-events) reports the verified completion, joined on `transactionId`.
* **Omitting the use case selects Reduce Churn.** A placement without `useCase` presents the Reduce Churn sheet, which can run a purchase. Select `rewardUsers` on every reward placement.

## Related

* [Reward Users](/publishers/use-cases/post-action-reward): the canonical description of this use case.
* The `placement()` reference for [iOS](/publishers/ios/sdk-reference/placement), [Android](/publishers/android/sdk-reference/placement), [React Native](/publishers/react-native/sdk-reference/placement), and [Flutter](/publishers/flutter/sdk-reference/placement): every builder method, including the use case and copy overrides.


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