> ## 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, method, callback and error of the Swift Video SDK.

All public types are `@MainActor`. Times are seconds; prices are CPM.

## `KontextVideo`

The entry point, one instance: `KontextVideo.shared`.

**initialize(with:completion:)** `method`

Starts the SDK: stores the configuration and calls the server in the background. Call it once, at app launch; later calls are ignored. `completion` runs on the main thread once the server answered or failed.

```swift theme={null}
KontextVideo.shared.initialize(with: .init(publisherToken: "…")) { state in … }
```

**initialize(with:)** `async method`

The same for `async` code; returns the resulting `State`: `.enabled`, `.disabled(reason:)` (the server switched the SDK off for this launch) or `.failed` (the server could not be reached; every ads request retries first).

```swift theme={null}
let state = await KontextVideo.shared.initialize(with: .init(publisherToken: "…"))
```

**user** `User?`

What you know about the viewer. Set it whenever you learn it; the next ads request carries it.

**regulatory** `Regulatory?`

Privacy and consent signals. The SDK reads TCF values from your consent platform's shared storage; set here what it did not write (COPPA always comes from you).

**variantId** `String?`

Selects which type of ad to render, for A/B tests agreed with Kontext.

**version** `String`

The SDK's version, as sent with every request. For your logs and crash reports.

## `KontextVideo.Configuration`

**publisherToken** `String` *required*

Identifies the publisher. Not a secret. You get a `{publisher}-dev` token for testing and a production one.

**requestTrackingAuthorization** `Bool`

Whether the SDK shows the App Tracking Transparency dialog itself, before its first ads request. Defaults to `false`: the app decides when the dialog appears.

**logLevel** `LogLevel`

How much the SDK prints to the console: `.none`, `.error`, `.warning` (default), `.info`, `.debug`.

## `KontextVideo.Content`

The video the ads are for. Everything beyond `id` and `language` is contextual signal.

**id** `String` *required*

Your own id of the video, any scheme.

**language** `String` *required*

BCP-47, for example `"en"` or `"pt-BR"`.

**mediaRating** `Rating?`

`.safe` or `.explicit`. Leave unset when you don't know; explicit content gets no ads that require safe content.

**url** `URL?`

The episode's public page.

**title** `String?`

**categories** `[String]?`

IAB Content Taxonomy 3.0 ids.

**description** `String?`

**duration** `TimeInterval?`

Seconds.

**episodeNumber** `Int?`

**keywords** `[String]?`

**genre** `String?`

For example `"romance"`.

**series** `Series?`

**Properties**

**id** `String` *required*

**title** `String?`

**description** `String?`

**episodeCount** `Int?`

Total number of episodes.

## `KontextVideo.User`

**id** `String?`

Your own unique identifier of the viewer.

**email** `String?`

Plain email address, when consent allows it. The server hashes it on arrival and never stores the plain address.

**emailHash** `String?`

SHA-256 of the normalized address (trimmed, lowercased, UTF-8), 64 lowercase hex characters.

**keywords** `[String]?`

The viewer's interests, in your own words.

## `KontextVideo.Regulatory`

**gdpr** `Bool?`

Whether the request is subject to GDPR.

**gdprConsent** `String?`

IAB TCF v2 consent string.

**coppa** `Bool?`

Whether the request is subject to COPPA. Cannot be read from the device.

**gpp** `String?`

IAB Global Privacy Platform string.

**gppSid** `[Int]?`

GPP section ids that apply.

**usPrivacy** `String?`

Legacy IAB US Privacy (CCPA) string.

## `AdFormat`

`.overlay`, `.pause`, `.linear`.

## `VideoAds`

The ads of one video. Create one per episode; creating it sends nothing. Any number can be alive at once.

**init(content:)** `initializer`

```swift theme={null}
let ads = VideoAds(content: KontextVideo.Content(id: "episode-1", language: "en"))
```

**format(\_:)** `async throwing method`

The ad for one format: the same `VideoAd` as last time while it is unshown and valid, a new one otherwise. A failed request returns the held ad when it is still valid.

Throws `noFill(reason:)`, `request(_:)`, `destroyed`, `disabled(reason:)`, `notInitialized`, `initializationFailed`, or `CancellationError` when your task is cancelled (the request itself continues).

```swift theme={null}
let ad = try await ads.format(.pause)
```

**trackPlayhead(of:)** `method`

Reads the content playhead from this `AVPlayer` whenever the SDK needs one. Held weakly; no observer is attached. Call it when this episode starts playing in the player.

**playheadProvider** `(() -\> TimeInterval)?`

Where the SDK reads the content playhead, in seconds, for any player. `trackPlayhead(of:)` sets it for you. Nothing set: 0, what a prefetch should send.

**destroy()** `method`

Releases the video's ads. Every held ad is dropped and the advertiser told it was not used; the ad on screen ends with `didEnd(.destroyed)`; a `format()` or `load()` in flight throws `destroyed`. Idempotent. Releasing the object does the same, best effort.

**content** `Content`

What it was created with.

**isDestroyed** `Bool`

`true` after `destroy()`.

## `VideoAd`

One ad, from the server's answer to the end of its presentation. Look at its facts, then `load()` or `reject()`, then `show()`, then exactly one `didEnd`. Shown at most once.

### Facts

**id** `String`

**format** `AdFormat`

**price** `Price`

**Properties**

**value** `Double`

CPM.

**currency** `String`

ISO 4217.

**precision** `Precision`

`.exact` (a DSP's clearing price) or `.estimated` (house demand, a forecast).

**duration** `TimeInterval?`

Overlay: how long the SDK keeps it on screen, `nil` when it stays until ended. Linear: the video's length. Always `nil` for a pause ad.

### State

**isLoaded** `Bool`

`load()` finished.

**isReady** `Bool`

Loaded, not shown, not rejected, not expired: `show()` can be tried. A hint, not a guarantee; `show()` still measures the view.

**invalidationReason** `InvalidationReason?`

Why the ad ended before it was shown, once it did: `.expired`, `.rejected`, `.destroyed`, `.creativeFailed(code:)`.

**wasShown** `Bool`

`true` from a successful `show()` on.

**hasEnded** `Bool`

`true` once the ad began to end. `didEnd` follows at once for an overlay or pause ad, and once the dismissal finished for a linear ad.

**isCompleted** `Bool`

Whether the creative ran to its end: a video reached complete, an overlay's duration elapsed. Separate from how it left the screen.

**delegate** `VideoAdDelegate?`

Receives the ad's moments. Held weakly.

### Methods

**load()** `async throwing method`

Renders the creative off screen and returns once the page reports it ready, so `show()` is instant. Throws `creativeFailed(code:)`, `invalidated(_:)`, `destroyed`, `disabled(reason:)`.

**reject(\_:)** `throwing method`

You won't use the ad; the server tells the advertiser. `.notUsed` (default) or `.outbid(winningPrice:winner:)`. Works until `show()`, loaded or not. Throws `alreadyShown` after it, or the invalidation if the ad already ended.

```swift theme={null}
try ad.reject(.outbid(winningPrice: 2.4, winner: "Other network"))
```

**show(in:)** `throwing method`

Shows an overlay or pause ad inside `view`, the one the content plays in. Succeeds once the ad is on screen. Throws, with nothing shown: `notLoaded`, `alreadyShown`, `anotherAdShowing`, `invalidated(_:)`, `destroyed`, `disabled(reason:)`, `presenterUnavailable` (the view is not on screen) and `containerTooSmall(minimum:)` (the ad stays ready in both), `wrongPresentation` (a linear ad).

**show(from:)** `throwing method`

Presents a linear ad full screen: from the given view controller, or with `nil` (the default) from the key window's top view controller. Throws, with nothing shown: the errors above plus `presenterUnavailable` (the ad stays ready), `wrongPresentation` (an overlay or pause ad).

```swift theme={null}
try linear.show()
try linear.show(from: viewController)
```

**dismiss()** `throwing method`

Ends an overlay or pause ad because you say so; `didEnd(.dismissed)` follows, synchronously. Before `show()` and after `didEnd` it does nothing. Throws `wrongPresentation` for a linear ad, which only the SDK dismisses.

## `VideoAdDelegate`

Delivered on the main actor. Every method has an empty default; implement the ones you need. Nothing is delivered before `show()`.

**videoAdDidRecordImpression(\_:)** `method`

The impression was counted: at `show()` for an image, at the first frame for a video. At most once; may not come at all.

**videoAd(\_:didClick:)** `method`

The viewer tapped the ad; the SDK opened `click.url`, or for an app-install ad the App Store product sheet inside your app. `click.area` is `.creative`, `.endCard` or `.other(String)`. Once per tap.

**videoAd(\_:didFail:)** `method`

The creative failed or stalled after presentation began. `didEnd(.failed)` follows right away.

**videoAd(\_:didEnd:)** `method`

Presentation is over. Exactly once per successful `show()`, always last. Resume your content here, whatever the reason.

## `VideoAd.EndReason`

| Reason | When |
| - | - |
| `.completed` | The ad ended by itself: an overlay's duration elapsed, a linear video finished with no end card. |
| `.skipped` | The viewer tapped Skip on a linear ad before the video ended. |
| `.closed` | The viewer tapped the ad's close control (an overlay's or pause card's ✕, a linear end card's ✕). A pause card's ✕ leaves the content paused. |
| `.resumed` | The viewer tapped Resume on a full-screen pause ad. |
| `.failed` | The creative failed or stalled, or the full-screen ad could not be presented; `didFail` came first. |
| `.interrupted` | The presentation disappeared for a reason the SDK did not cause: the view left the window, the presenting controller was dismissed. Noticed within about half a second. |
| `.dismissed` | You called `dismiss()`. |
| `.destroyed` | You called `destroy()`. |

## `VideoAdError`

Thrown, never delivered through the delegate: a thrown error means nothing happened on screen and nothing was fired.

| Error | When |
| - | - |
| `.notInitialized` | `initialize(with:)` was never called. |
| `.initializationFailed` | The server could not be reached, and the retry failed too. Every `format()` retries. |
| `.destroyed` | The `VideoAds` was destroyed. Create a new one for the next content. |
| `.disabled(reason:)` | The server switched the SDK off for this launch. |
| `.noFill(reason:)` | The server had nothing for this format. See `NoFillReason`. |
| `.request(Error)` | The request failed and no valid ad was held for the format. |
| `.creativeFailed(code:)` | The creative did not load within 10 s of active time; `code` is the VAST error code. |
| `.alreadyShown` | Shown once; cannot be shown again or rejected. |
| `.anotherAdShowing` | Another ad is on screen, from any `VideoAds`. This ad stays ready. |
| `.invalidated(reason)` | The ad ended before it was shown: `.expired`, `.rejected`, `.destroyed`, `.creativeFailed(code:)`. |
| `.notLoaded` | `show()` before `load()` finished. The ad stays as it was. |
| `.containerTooSmall(minimum:)` | The ad would have to shrink below 50 % to fit. The ad stays ready. |
| `.presenterUnavailable` | Nothing on screen can hold the ad right now: no view controller can present the linear ad, or the view given for an overlay or pause ad is not in a window. The ad stays ready. |
| `.wrongPresentation` | `show()` on an overlay or pause ad, `show(in:)` or `dismiss()` on a linear ad. |

## `VideoAdError.NoFillReason`

| Reason | Meaning |
| - | - |
| `.noAdMatch` | No campaign matched the content, the viewer or the moment |
| `.frequencyCap` | The viewer reached the frequency cap set for your app. Only when a cap is configured |
| `.contentUnsafe` | The content is not brand safe |
| `.geoRestricted` | Not served in this country |
| `.formatNotEnabled` | The format is not enabled for your app |
| `.temporaryError` | Our side; ask again later |
| `.alreadyUsed` | The SDK's own: the answer was an ad you had just shown or rejected |
| `.unknown` | The server gave no reason |
| `.other(String)` | A reason this SDK version does not know, passed through unchanged |


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