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

# InAppEventType: the in-app event enum and the aliasing rejections

> Why the mobile SDKs report engagement through the InAppEventType enum, which three values the server accepts, and how to fix the 422 you get when a raw string or an alias slips through.

# InAppEventType: the in-app event enum and the aliasing rejections

The mobile SDKs report in-app engagement (impression / click / dismiss) with one typed enum. This page is the contract for that enum: what the server accepts, what it rejects with a 422, and the exact fix per language.

## 1. Why mobile does not speak raw strings

Every engagement event lands on one endpoint: `POST /sdk/in-app/events`. The server validates `type` against a fixed set — `impression`, `click`, `dismiss` — before it writes the event into your analytics, so the same visitor's journey reads as one event family on the contact timeline.

The SDKs expose that set as a typed enum rather than an open string, so a mistyped value fails at compile time in your IDE instead of at runtime against the API. In TypeScript/React Native the enum is a string-literal union, so the compiler rejects anything outside the three literals before the event ever leaves the device.

When an invalid value does reach the server — a hand-rolled HTTP call, or a value an older SDK passed through unchecked — the response is a `422` validation error and the event is dropped. Nothing is written, and no retry will change the outcome until the value is corrected.

## 2. The three allowed values

Exactly three event types are accepted, with one meaning each:

| Wire value   | Report when                                                                                | SDK enum                                                                             |
| ------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| `impression` | A surface rendered on screen. Report exactly once per render of a card or message.         | Swift `.impression` · Kotlin/Java `InAppEventType.IMPRESSION` · RN/TS `"impression"` |
| `click`      | The visitor tapped the surface or one of its buttons (pass the button id for button taps). | Swift `.click` · Kotlin/Java `InAppEventType.CLICK` · RN/TS `"click"`                |
| `dismiss`    | The visitor dismissed the surface. `dismiss(...)` on the client reports this for you.      | Swift `.dismiss` · Kotlin/Java `InAppEventType.DISMISS` · RN/TS `"dismiss"`          |

These are the only bases the server order-reads. Any other string is rejected.

## 3. Forbidden shapes — each rejected with a 422

All three of these compile in at least one language and then fail at the API:

**Raw string literals where the language offers a real enum.** On Android the Kotlin enum exists, so a literal gets past no compiler check you couldn't have caught:

```kotlin theme={null}
// Android — rejected: a raw string bypasses InAppEventType.
inApp.reportEvent("impression", feed.cards.first().id)
```

**Free-form camelCase or snake\_case aliases.** The server does no aliasing or case-folding — the value must be one of the three exact lowercase strings above:

```typescript theme={null}
// React Native / TypeScript — rejected: 'page_view' is not a member of the union.
inApp.reportEvent("page_view", feed.cards[0].id);
```

**Helper-class or analytics-style names.** Names like `OrbitAnalytics.IMPRESSION` or `"InAppEventType.CLICK"` read as plausible references but carry a value the server has never heard of:

```swift theme={null}
// iOS — rejected: the string value of a namespaced reference is not 'impression'.
inApp.reportEvent("OrbitAnalytics.impression", surfaceId: feed.cards[0].id)
```

The fix is always the same: pass the enum case, or in TypeScript the exact literal.

## 4. The fix, per language

**Swift (iOS)** — `InAppEventType` is a `String`-backed enum; use member shorthand:

```swift theme={null}
let feed = await inApp.fetchFeed()
await inApp.reportEvent(.impression, surfaceId: feed.cards[0].id)
```

**Kotlin / Java (Android)** — `InAppEventType` carries its wire value; import the enum and reference the case:

```kotlin theme={null}
import io.orbit.devotel.inapp.InAppEventType

val feed = inApp.fetchFeed()
inApp.reportEvent(InAppEventType.IMPRESSION, feed.cards.first().id)
```

**React Native / TypeScript** — `InAppEventType` is the string-literal union `"impression" | "click" | "dismiss"`, so the literal is the enum and the compiler enforces it:

```typescript theme={null}
const feed = await inApp.fetchFeed();
await inApp.reportEvent("impression", feed.cards[0].id);
```

## 5. The same event in all three languages

Reporting one impression for the first card in the feed:

```swift theme={null}
// Swift
await inApp.reportEvent(.impression, surfaceId: feed.cards[0].id)
```

```kotlin theme={null}
// Kotlin
inApp.reportEvent(InAppEventType.IMPRESSION, feed.cards.first().id)
```

```typescript theme={null}
// TypeScript (React Native)
await inApp.reportEvent("impression", feed.cards[0].id);
```

All three serialize to the identical wire body — `{ "type": "impression", "surface_id": "…", "anonymous_id": "…" }` — so a visitor who moves between your iOS, Android, and React Native apps lands one consistent engagement history.

## 6. Debugging the 422 payload

A rejected event comes back as the standard Orbit error envelope. `type` failures surface as a `VALIDATION_ERROR` whose `details.issues` pin the offending field:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid enum value for 'type'",
    "status": 422,
    "details": {
      "issues": [
        { "path": ["type"], "message": "Invalid enum value. Expected 'impression' | 'click' | 'dismiss'" }
      ]
    }
  }
}
```

Read `details.issues[0].path` — when it points at `type`, compare the rejected value against the table in section 2 and switch to the enum form from section 4. Because `reportEvent` is fire-and-forget in every SDK, a rejection never throws into your UI; if you need to see it, enable the client's `debug` flag and the rejection is logged with the value that failed. Correct the value and re-send — the event idempotency contract dedupes a corrected re-send of the same event.

## Where to go next

* [Swift SDK](/sdks/swift) — full iOS quickstart.
* [Android SDK](/sdks/android) — full Kotlin quickstart.
* [React Native SDK](/sdks/react-native) — full RN quickstart.
* [Build the in-app engagement channel](/guides/in-app-channel-messages) — authoring and targeting the surfaces these events measure.
