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

# API reference

> Every type and method exposed by the Kotlin SDK.

## `KontextAds.createSession(...)`

```kotlin theme={null}
public fun createSession(context: Context, options: SessionOptions): Session
```

Returns a new `Session` configured from the given `SessionOptions`. Fires `/init` in the background. Pass `context.applicationContext` so the session is not tied to any single Activity.

## `SessionOptions`

<ParamField path="publisherToken" type="String" required>
  Your unique publisher token.
</ParamField>

<ParamField path="userId" type="String" required>
  Stable identifier for the end user. Used for personalization, frequency capping, and rewarded ads.
</ParamField>

<ParamField path="conversationId" type="String" required>
  Unique ID of the current conversation / chat thread.
</ParamField>

<ParamField path="enabledPlacementCodes" type="List<String>?" optional>
  Placement codes to request ads for. Defaults to `["inlineAd"]` when null or empty.
</ParamField>

<ParamField path="adServerUrl" type="String?" optional>
  Override for the ad-server base URL. Leave null to use Kontext's production endpoint.
</ParamField>

<ParamField path="character" type="Character?" optional>
  AI character metadata for contextual targeting.

  <Expandable title="Properties">
    <ParamField path="id" type="String" required />

    <ParamField path="name" type="String" required />

    <ParamField path="avatarUrl" type="URI" required>A `java.net.URI` — construct with `URI.create("…")`, not a raw `String`.</ParamField>

    <ParamField path="greeting" type="String?" optional />

    <ParamField path="persona" type="String?" optional />

    <ParamField path="tags" type="List<String>?" optional />

    <ParamField path="isNsfw" type="Boolean?" optional />
  </Expandable>
</ParamField>

<ParamField path="variantId" type="String?" optional>
  Publisher-defined cohort identifier (e.g. for A/B testing).
</ParamField>

<ParamField path="regulatory" type="Regulatory?" optional>
  Privacy / consent signals. TCF (`gdpr` / `gdprConsent`) is collected automatically if a TCF-compliant CMP is integrated — set manually only for COPPA, GPP, or US Privacy.

  <Expandable title="Properties">
    <ParamField path="gdpr" type="Int?" optional>0, 1, or null.</ParamField>
    <ParamField path="gdprConsent" type="String?" optional>IAB TCF v2 consent string.</ParamField>
    <ParamField path="coppa" type="Int?" optional>0, 1, or null.</ParamField>
    <ParamField path="gpp" type="String?" optional>Global Privacy Platform string.</ParamField>
    <ParamField path="gppSid" type="List<Int>?" optional>GPP section IDs that apply.</ParamField>
    <ParamField path="usPrivacy" type="String?" optional>CCPA / LSPA string.</ParamField>
  </Expandable>
</ParamField>

<ParamField path="userEmail" type="String?" optional>
  End-user email for frequency-cap deduplication.
</ParamField>

<ParamField path="advertisingId" type="String?" optional>
  GAID you collected yourself. Takes priority over the SDK's automatic collection.
</ParamField>

<ParamField path="onEvent" type="(AdEvent) -> Unit" optional>
  Callback invoked on every ad lifecycle event. Called on the main thread.
</ParamField>

<ParamField path="onDebugEvent" type="(String, Any?) -> Unit" optional>
  Optional diagnostic stream — fires for every internal SDK event (preload start/end, iframe lifecycle, geometry updates, etc.). Useful during integration. Leave null in production.
</ParamField>

## `Session`

<ParamField path="addMessage(message, options)" type="method">
  Append a `Message` to the conversation. Synchronous (not `suspend`). User messages trigger a debounced preload; assistant messages let the SDK link the matched ad to the placement.

  ```kotlin theme={null}
  session.addMessage(Message(id = "m1", role = Role.USER, content = "Hi"))
  session.addMessage(
      Message(id = "m2", role = Role.USER, content = "Hi again"),
      AddMessageOptions(trackOnly = true),
  )
  ```

  When `trackOnly = true`, the preload is sent for analytics but no ad is generated.
</ParamField>

<ParamField path="createAd(messageId, options)" type="method">
  Returns an `Ad` for the given `messageId`. Idempotent — repeated calls with the same `messageId` + `code` + `theme` return the same `Ad`. Cache the result.

  ```kotlin theme={null}
  val ad = session.createAd("m2")
  val sidebar = session.createAd("m2", AdOptions(code = "sidebar", theme = "dark"))
  ```
</ParamField>

<ParamField path="updateOptions(partial)" type="method">
  Live-update preload-scoped fields. See [Guides → Live-updating session options](/sdk/kotlin/guides#live-updating-session-options).
</ParamField>

<ParamField path="destroy()" type="method">
  Tear down the session: cancel preloads, destroy ads, release WebView resources. Idempotent. `close()` is an alias (implements `AutoCloseable`).
</ParamField>

<ParamField path="events" type="SharedFlow<AdEvent>" property>
  Hot Flow that delivers the same events as `onEvent`. Useful for ViewModels and coroutine pipelines.
</ParamField>

<ParamField path="messages" type="List<Message>" property>
  Read-only snapshot of messages tracked by the session.
</ParamField>

<ParamField path="sessionId" type="UUID?" property>
  Server-assigned session ID. `null` until the first successful preload.
</ParamField>

<ParamField path="disabled" type="Boolean" property>
  `true` if the server has permanently disabled the session via the `/init` response (e.g. geo-restriction). Subsequent preloads are skipped.
</ParamField>

<ParamField path="destroyed" type="Boolean" property>
  `true` after `destroy()` is called.
</ParamField>

## `MutablePublisherOptions`

Subset of `SessionOptions` accepted by `session.updateOptions(...)`. Every field is optional — non-null overwrites, null leaves unchanged.

<ParamField path="variantId" type="String?" optional />

<ParamField path="regulatory" type="Regulatory?" optional />

<ParamField path="userEmail" type="String?" optional />

<ParamField path="advertisingId" type="String?" optional />

## `Message`

<ParamField path="id" type="String" required>Unique message ID.</ParamField>
<ParamField path="role" type="Role" required>`Role.USER` or `Role.ASSISTANT`.</ParamField>
<ParamField path="content" type="String" required>Message text.</ParamField>
<ParamField path="createdAt" type="Date" optional>Defaults to `Date()`.</ParamField>

## `AdOptions`

<ParamField path="code" type="String" optional>Placement code. Defaults to `"inlineAd"`.</ParamField>
<ParamField path="theme" type="String?" optional>UI theme hint forwarded to the ad iframe (e.g. `"dark"`).</ParamField>

## `AddMessageOptions`

<ParamField path="trackOnly" type="Boolean" optional>
  When `true`, the preload is still sent (for analytics) but no ad is generated for this message. Defaults to `false`.
</ParamField>

## UI

### `InlineAd` (Compose, recommended)

```kotlin theme={null}
@Composable
public fun InlineAd(
    messageId: String,
    session: Session,
    code: String? = null,
    theme: String? = null,
    modifier: Modifier = Modifier,
)
```

Mounts the ad for the given `messageId`. Internally calls `session.createAd(...)`, attaches a pooled `WebView`, and reports container geometry back to the iframe. Safe to compose in a `LazyColumn` — the underlying `Ad` and `WebView` survive recomposition and scroll-off-screen recycling.

A second overload accepts a pre-resolved `Ad` directly:

```kotlin theme={null}
@Composable
public fun InlineAd(ad: Ad, modifier: Modifier = Modifier)
```

### `InlineAdView` (View interop)

```kotlin theme={null}
public class InlineAdView(context: Context) : FrameLayout {
    public var onHeightChange: ((Float) -> Unit)?
    public fun bind(messageId: String, session: Session, code: String? = null, theme: String? = null)
}
```

For apps not on Compose. Call `bind(messageId, session)` once after inflating; observe `onHeightChange` to resize the surrounding container (e.g. in a `RecyclerView` row).

## `AdEvent`

`AdEvent` is a sealed class with one typed payload per case. Every case has a stable string identifier accessible via `event.name`.

### `AdEvent.Filled` — wire name `ad.filled`

An ad was returned and linked to the placement.

<Expandable title="Filled">
  <ParamField path="bidId" type="UUID" />

  <ParamField path="code" type="String">Placement code this ad was matched to. Required for publishers with multiple `enabledPlacementCodes`.</ParamField>

  <ParamField path="revenue" type="Double?" />
</Expandable>

### `AdEvent.NoFill` — wire name `ad.no-fill`

No ad was returned for the placement (server skipped).

<Expandable title="NoFill">
  <ParamField path="skipCode" type="String">Reason the ad was skipped.</ParamField>
</Expandable>

### `AdEvent.AdHeight` — wire name `ad.height`

The ad iframe reported a new height. Use to size the surrounding container in `RecyclerView` rows. The `InlineAd` Compose composable handles this for you automatically.

<Expandable title="AdHeight">
  <ParamField path="bidId" type="UUID" />

  <ParamField path="messageId" type="String" />

  <ParamField path="height" type="Float" />
</Expandable>

### `AdEvent.Viewed` — wire name `ad.viewed`

The ad was viewed by the user (IAB MRC viewability standard).

<Expandable title="Viewed">
  <ParamField path="bidId" type="UUID" />

  <ParamField path="content" type="String" />

  <ParamField path="messageId" type="String" />

  <ParamField path="format" type="String" />

  <ParamField path="revenue" type="Double?" />
</Expandable>

### `AdEvent.Clicked` — wire name `ad.clicked`

The user clicked the ad.

<Expandable title="Clicked">
  <ParamField path="bidId" type="UUID" />

  <ParamField path="content" type="String" />

  <ParamField path="messageId" type="String" />

  <ParamField path="url" type="String" />

  <ParamField path="format" type="String" />

  <ParamField path="area" type="String">Region of the ad that was clicked.</ParamField>
</Expandable>

### `AdEvent.RenderStarted` — wire name `ad.render-started`

The first token of the ad content was received.

<Expandable title="RenderStarted">
  <ParamField path="bidId" type="UUID" />
</Expandable>

### `AdEvent.RenderCompleted` — wire name `ad.render-completed`

Ad content streaming finished.

<Expandable title="RenderCompleted">
  <ParamField path="bidId" type="UUID" />
</Expandable>

### `AdEvent.Error` — wire name `ad.error`

The SDK encountered an error while serving an ad.

<Expandable title="Error">
  <ParamField path="message" type="String" />

  <ParamField path="errCode" type="String" />
</Expandable>

### `AdEvent.VideoStarted` — wire name `video.started`

<Expandable title="VideoStarted">
  <ParamField path="bidId" type="UUID" />
</Expandable>

### `AdEvent.VideoCompleted` — wire name `video.completed`

<Expandable title="VideoCompleted">
  <ParamField path="bidId" type="UUID" />
</Expandable>

### `AdEvent.RewardGranted` — wire name `reward.granted`

Fired for rewarded-ad flows after the user qualifies for a reward.

<Expandable title="RewardGranted">
  <ParamField path="bidId" type="UUID" />
</Expandable>
