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

# DismissReason

> How a presented offer sheet went away

The `dismissal` axis of a presented flow's [`Outcome`](./presentation-result): how the sheet actually ended. These are business outcomes, not errors. Genuine failures arrive as values in `.notPresented(.error(EncoreError))`, never here.

`DismissReason` is a `String`-backed enum. The raw values are the analytics wire values: the same string lands in `decline_reason` on `sdk_offer_sheet_dismissed`, unmapped.

## Definition

```swift theme={null}
public enum DismissReason: String, CaseIterable, Equatable, Sendable {
    case userTappedClose   = "close_button"
    case userSwipedDown    = "swipe_dismiss"
    case userCancelled     = "user_cancelled"
    case lastOfferDeclined = "last_offer_declined"
    case dismissed         = "dismissed"
    case cooldown          = "provisional_cooldown"
    case flowCompleted     = "flow_completed"
    case interrupted       = "interrupted"

    // Emission-only cases (never carried on Outcome.dismissal):
    case offerClaimed      = "offer_claimed"
    case appBackgrounded   = "app_backgrounded"
    case appTerminated     = "app_terminated"
}
```

## Cases

| Case                 | Description                                                                                                                                |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `.userTappedClose`   | User tapped the close / "No thanks" button on the sheet.                                                                                   |
| `.userSwipedDown`    | User swiped down to dismiss the sheet.                                                                                                     |
| `.userCancelled`     | User cancelled mid-flow.                                                                                                                   |
| `.lastOfferDeclined` | Retained for analytics wire compatibility. The SDK currently emits it only when a strict-mode claim ends with no transaction id to verify. |
| `.dismissed`         | Generic dismissal when the specific gesture is unknown.                                                                                    |
| `.cooldown`          | Claim rejected server-side (HTTP 409, cross-offer provisional cooldown).                                                                   |
| `.flowCompleted`     | The flow finished on its own and the SDK closed the sheet.                                                                                 |
| `.interrupted`       | The SDK force-ended a dead flow (structural reconciliation), not the user.                                                                 |

`dismissal` always records how the sheet actually ended: `.flowCompleted` when the SDK closed it on its own; the user's gesture when a post-claim or success screen kept it up and they closed it themselves.

The last three cases (`.offerClaimed`, `.appBackgrounded`, `.appTerminated`) are emission-only analytics values. `Outcome.dismissal` never carries them: a claim is advertiser-axis data, and the two lifecycle interruptions fire while the sheet is still up.

<Note>
  Reasons a sheet never appeared at all (`.noOffers`, `.unsupportedOS`, `.experimentControl`, `.notConfigured`, `.alreadyPresenting`, `.useCaseUnavailable`, `.error`) live on [`NotPresentedReason`](./presentation-result#notpresentedreason), not here.
</Note>

## Usage

Most apps never branch on the dismissal: the canonical check is on the claim and purchase facts, and every non-success falls through to the original flow.

```swift theme={null}
let result = await Encore.shared.placement("cancel_flow").show()

if result.claim != nil || result.publisher == .purchased {
    // Claimed or purchased: continue the unlocked path.
} else {
    if let dismissal = result.dismissal {
        analytics.track("offer_dismissed", ["reason": dismissal.rawValue])
    }
    // In every case, let the user continue.
    proceedWithCancellation()
}
```

## Related Types

* [PresentationResult](./presentation-result), the record `dismissal` is one axis of.
* [Errors](./errors), genuine failures carried as values on `.notPresented(.error(...))`.
