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

# Models

> The Almedia API — SDK 1.3.0 and newer. Synced from the source repository.

## `AlmediaStatus`

Namespace: `AlmediaSDK` · abstract class

The player's status. [`Status`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-properties#static-almediastatus-status--get-) holds it and [`OnStatusChanged`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediastatus%3E-onstatuschanged) delivers every change. Each status is a nested sealed class that carries its own data.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public abstract class AlmediaStatus : IEquatable<AlmediaStatus>
{
    public sealed class NotInitialized : AlmediaStatus { public NotInitialized(); }
    public sealed class Eligible       : AlmediaStatus { public Eligible(); }

    public sealed class Linked : AlmediaStatus
    {
        public Linked(bool canShowRewardHub, bool canShowOffer);
        public bool CanShowRewardHub { get; }
        public bool CanShowOffer     { get; }
    }

    public sealed class NotAvailable : AlmediaStatus
    {
        public NotAvailable(string rawReason);
        public AlmediaNotAvailableReason Reason    { get; }
        public string                    RawReason { get; }
    }

    public sealed class Blocked  : AlmediaStatus { public Blocked(); }
    public sealed class Disabled : AlmediaStatus { public Disabled(); }
}
```

| Status | Meaning |
| - | - |
| `NotInitialized` | Before `Initialize` resolves the first status, and while it applies a different configuration. |
| `Eligible` | Service is available and the player has not linked yet. Linking UI should be visible. [`ShowLink()`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-methods#static-void-showlink) presents the link popup. |
| `Linked` | Player has linked their Freecash account. Reward notifications can flow. |
| `NotAvailable` | Service is not available for this user (region, eligibility, holdout). Linking UI should hide. `Reason` says why. |
| `Blocked` | User is blocked by the backend (abuse, fraud). Linking UI should hide. Unlike `NotAvailable`, retrying does not help. |
| `Disabled` | Integration is killswitched at the backend level. SDK runs in a no-op mode until the backend re-enables it. |

| Member | Notes |
| - | - |
| `Linked.CanShowRewardHub` | `ShowRewardHub()` would present a screen right now. |
| `Linked.CanShowOffer` | `ShowOffer()` would present a screen right now. |
| `NotAvailable.Reason` | Why the service is not available. See [`AlmediaNotAvailableReason`](https://docs.almedia.dev/technical/api-reference/almedia/models#almedianotavailablereason). Never `null`. |
| `NotAvailable.RawReason` | The reason exactly as the server sent it. Empty when the server sent none. `Reason` is parsed from it. |

Test a status with a type pattern. Keep a `default` branch in a `switch`: a later version can add statuses.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
switch (Almedia.Status)
{
    case AlmediaStatus.Eligible:
        ShowLinkButton();
        break;
    case AlmediaStatus.Linked { CanShowRewardHub: true }:
        ShowRewardHubButton();
        break;
    default:
        HideEntryPoints();
        break;
}
```

**The flags are live.** A `Linked` player can have either flag `false` - a reward hub the backend has withdrawn, or an offer that has not appeared yet - and the flags can flip between syncs while the player stays linked. Each change arrives as a new `Linked` status through `OnStatusChanged`.

Statuses compare by value. Two `Linked` statuses with the same flags are equal, and so are two `NotAvailable` statuses with the same `RawReason`. `ToString()` includes the data of `Linked` and `NotAvailable`, for example `Linked(canShowRewardHub: True, canShowOffer: False)`, and returns the class name for the other statuses.

Every constructor is public, so a test can build any status and deliver it with [`AlmediaEditorMock.EmitStatus`](https://docs.almedia.dev/technical/api-reference/almedia/editor-testing#static-void-emitstatus-almediastatus-status).

***

## `AlmediaNotAvailableReason`

Namespace: `AlmediaSDK` · sealed class

Why the status is `NotAvailable`. Read it from `Reason` on [`AlmediaStatus.NotAvailable`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediastatus). Only the static members below exist. Compare them with `==`. `ToString()` returns the member name.

| Member | Meaning |
| - | - |
| `Unknown` | The backend sent no reason, or one this SDK version does not recognize. Not an error - read it as "not available, cause unspecified". |
| `Holdout` | The player is in the holdout (control) group and is deliberately excluded from the Link experience. |
| `Disabled` | The game declared `Linking` in its [disabled features](https://docs.almedia.dev/technical/api-reference/almedia/models.md#almediafeature). |

A reason added by the backend later reads as `Unknown` in an existing build, and `RawReason` keeps the string the server sent. Handle `Unknown` as a real case.

The reason never changes what the SDK does - the entry point hides on `NotAvailable` whatever the reason. Use it for analytics, support diagnostics, and messaging:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
Almedia.OnStatusChanged += status =>
{
    if (status is AlmediaStatus.NotAvailable notAvailable
        && notAvailable.Reason == AlmediaNotAvailableReason.Holdout)
        Analytics.Track("link_holdout");
};
```

***

## `AlmediaError`

Namespace: `AlmediaSDK` · sealed class

Immutable error payload passed to `OnErrorOccurred`.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public AlmediaErrorCode Code    { get; }
public string           Message { get; }

public AlmediaError(AlmediaErrorCode code, string message);
```

| Property | Notes |
| - | - |
| `Code` | See [`AlmediaErrorCode`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediaerrorcode). Unrecognized native codes map to `Unknown`. Never `null`: the constructor reads a `null` code as `Unknown`. |
| `Message` | Human-readable string. May contain native-side detail; safe to log, but do not rely on its format for branching. |

Errors compare by value: two errors with the same code and message are equal.

***

## `AlmediaErrorCode`

Namespace: `AlmediaSDK` · sealed class

Only the static members below exist. Compare them with `==`. `ToString()` returns the member name.

| Member | Source | Typical cause |
| - | - | - |
| `Unknown` | Native | Unrecognized native code (version mismatch). |
| `InvalidConfiguration` | Local or native | Missing integration key, malformed config. Local errors fire synchronously from `Initialize`. |
| `NetworkFailure` | Native | Native HTTP request did not complete (offline, DNS, timeout). |
| `ServerError` | Native | Backend returned 5xx. |
| `RateLimited` | Native | Backend returned 429. |
| `Disabled` | Native | Integration is killswitched. SDK will not function until re-enabled. |
| `LinkingFailed` | Native | The linking flow ended without success (user closed, backend rejected). |
| `InvalidState` | Native | Method called in a state it does not support. |
| `Unexpected` | Native | Catch-all for uncaught native exceptions. |

***

## `AlmediaNotification`

Namespace: `AlmediaSDK` · class

Immutable reward-notification payload delivered via `OnNotificationsReceived`.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public string           Id         { get; }
public string           Title      { get; }
public string           Message    { get; }
public string           Timestamp  { get; }
public DateTimeOffset?  ReceivedAt { get; }
public string           Display    { get; }
public string           IconUrl    { get; }

[Obsolete] public string Type      { get; }   // alias of Display

public AlmediaNotification(string id, string title, string message, string timestamp, string display, string iconUrl);
[Obsolete] public AlmediaNotification(string id, string title, string message, string timestamp, string type);
```

| Property | Notes |
| - | - |
| `Id` | Stable, unique per notification. Use for dedup and tracking. |
| `Title` | Short headline. |
| `Message` | Body. May be multi-line; render in a wrapping text element. |
| `Timestamp` | Raw ISO 8601 string as delivered by the backend (e.g. `"2025-03-15T10:30:00Z"`). Preserved for logging / re-serialization; prefer `ReceivedAt` for display logic. |
| `ReceivedAt` | Parsed UTC `DateTimeOffset?`, or `null` when `Timestamp` is empty or unparseable. Always normalized to UTC (offset 0), so `DateTimeOffset.UtcNow - notification.ReceivedAt.Value` gives the elapsed time directly. |
| `Display` | Presentation hint: `"popup"` or `"tray"`. Open set - treat values you do not recognize as `"popup"`. Never null or empty. |
| `IconUrl` | Absolute URL of the notification's icon, or `null`. The bundled UI does not render it; the notification prefab supplies the row icon. In custom UI, load it yourself and fall back to your own art when null or unreachable. |
| `Type` | **Obsolete.** Alias of `Display`. Until 1.2.0 this carried a free-form category (`"reward"`, `"status"`); those values no longer exist on the wire, so comparisons against them never match. |

The constructor reads an empty `display` as `"popup"` and an empty `iconUrl` as `null`, and parses `ReceivedAt` from `timestamp`. Tests pass notifications built this way to [`AlmediaEditorMock.EmitNotifications`](https://docs.almedia.dev/technical/api-reference/almedia/editor-testing#static-void-emitnotifications-params-almedianotification-notifications).

***

## `AlmediaInGameRewardGrant`

Namespace: `AlmediaSDK` · class

An in-game-reward grant delivered via [`OnInGameRewardGrantRequested`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediaingamerewardgrant%3E-oningamerewardgrantrequested). Every reward in `Rewards` was granted together and belongs to one celebration.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public string                             Id         { get; }
public string                             Timestamp  { get; }
public DateTimeOffset?                    ReceivedAt { get; }
public IReadOnlyList<AlmediaInGameReward> Rewards    { get; }

public AlmediaInGameRewardGrant(string id, string timestamp, params AlmediaInGameReward[] rewards);
```

| Property | Notes |
| - | - |
| `Id` | Server-issued and unique per grant; a redelivery repeats it. The dedup key for hosts that want exactly-once crediting. |
| `Timestamp` | Raw ISO 8601 string of when the backend issued the grant. |
| `ReceivedAt` | Parsed UTC `DateTimeOffset?`, or `null` when `Timestamp` is empty or unparseable. |
| `Rewards` | The reward line items. At least one entry. |

The constructor throws `ArgumentException` when `rewards` is empty.

***

## `AlmediaInGameReward`

Namespace: `AlmediaSDK` · class

One reward line item of an [`AlmediaInGameRewardGrant`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediaingamerewardgrant).

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public double Amount { get; }
public string Code   { get; }

public AlmediaInGameReward(double amount, string code);
```

| Property | Notes |
| - | - |
| `Amount` | Amount to credit. Whole today, but the contract permits fractions - do not truncate to an integer. |
| `Code` | Reward code agreed with Almedia (e.g. `"gems"`, `"spins"`). Treat unrecognized codes as a no-op rather than an error. |

***

## `AlmediaProgress`

Namespace: `AlmediaSDK` · sealed class

A snapshot of the player's progress in this game. [`Progress`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-properties#static-almediaprogress-progress--get-) exposes it and [`OnProgressUpdated`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediaprogress%3E-onprogressupdated) delivers it. A snapshot is never partial. A newer snapshot replaces the previous one. The SDK does not merge snapshots.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public string                              Id        { get; }
public string                              Timestamp { get; }
public DateTimeOffset?                     BuiltAt   { get; }
public string                              Username  { get; }
public AlmediaRewardPoints                 Balance   { get; }
public AlmediaRewardPoints                 Earned    { get; }
public IReadOnlyList<AlmediaTask>          Pending   { get; }
public IReadOnlyList<AlmediaCompletedTask> Completed { get; }
public IReadOnlyList<AlmediaTask>          Expired   { get; }

public AlmediaProgress(string id, string timestamp, string username, AlmediaRewardPoints balance, AlmediaRewardPoints earned,
    IReadOnlyList<AlmediaTask> pending, IReadOnlyList<AlmediaCompletedTask> completed, IReadOnlyList<AlmediaTask> expired);
```

| Property | Notes |
| - | - |
| `Id` | Opaque and unique for each snapshot. It has no order. Compare `BuiltAt` instead. |
| `Timestamp` | Raw ISO 8601 string. The time when the server built the snapshot. |
| `BuiltAt` | Parsed UTC `DateTimeOffset?`. `null` when `Timestamp` is empty or not valid. |
| `Username` | The player's username. `null` when the server sent none. A newer snapshot without a username clears the previous value. |
| `Balance` | The player's total balance. |
| `Earned` | The total the player earned in this game. |
| `Pending` | Tasks the player can still do in this game. Not more than one entry for each task. |
| `Completed` | One entry for each completion, newest first. The server limits the number of entries. |
| `Expired` | Tasks the player can no longer complete. The server can limit the number of entries. |

The constructor copies the lists, reads a `null` list as empty and reads an empty username as `null`.

***

## `AlmediaTask`

Namespace: `AlmediaSDK` · sealed class

A task the player can do in this game to earn a reward.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public string              Id                     { get; }
public string              Kind                   { get; }
public string              Title                  { get; }
public AlmediaRewardPoints Reward                 { get; }
public AlmediaTaskProgress Progress               { get; }
public string              RewardDropsAtTimestamp { get; }
public DateTimeOffset?     RewardDropsAt          { get; }

public AlmediaTask(string id, string kind, string title, AlmediaRewardPoints reward,
    AlmediaTaskProgress progress = null, string rewardDropsAtTimestamp = null);
```

| Property | Notes |
| - | - |
| `Id` | Opaque and stable across snapshots and reward decreases. It identifies the task, not one completion. |
| `Kind` | Groups similar tasks. One of [`AlmediaTaskKind`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediataskkind). The set is open. Treat an unknown value as `AlmediaTaskKind.Main`. |
| `Title` | The title to show the player. |
| `Reward` | The reward for one completion. |
| `Progress` | The player's progress, or `null` for a yes-or-no task. |
| `RewardDropsAtTimestamp` | Raw ISO 8601 string. The time of the next `Reward` decrease, or `null` when none is scheduled. |
| `RewardDropsAt` | Parsed UTC `DateTimeOffset?`. `null` when `RewardDropsAtTimestamp` is `null` or not valid. |

The constructor reads an empty `rewardDropsAtTimestamp` as `null`.

***

## `AlmediaTaskKind`

Namespace: `AlmediaSDK` · static class

The known values of [`AlmediaTask.Kind`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediatask), as `const string` members. The server can add more.

| Member | Value | Notes |
| - | - | - |
| `Main` | `"main"` | A regular task. |
| `PurchaseBonus` | `"purchaseBonus"` | Pays when the player makes a purchase. |
| `Burning` | `"burning"` | Its reward decreases on a schedule. See `AlmediaTask.RewardDropsAt`. |
| `BurningPurchaseBonus` | `"burningPurchaseBonus"` | A purchase bonus whose reward decreases on a schedule. |
| `TimeLimited` | `"timeLimited"` | Must be completed before a deadline. |
| `Daily` | `"daily"` | Can be completed once a day. |
| `Play` | `"play"` | Pays for time played. |
| `Unlimited` | `"unlimited"` | Can be completed any number of times. |

***

## `AlmediaTaskProgress`

Namespace: `AlmediaSDK` · sealed class

The progress of an [`AlmediaTask`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediatask).

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public long Value  { get; }
public long Target { get; }

public AlmediaTaskProgress(long value, long target);
```

| Property | Notes |
| - | - |
| `Value` | The value reached so far. |
| `Target` | The value needed to complete the task. |

***

## `AlmediaCompletedTask`

Namespace: `AlmediaSDK` · sealed class

One completion of an [`AlmediaTask`](https://docs.almedia.dev/technical/api-reference/almedia/models#almediatask). A player can complete the same task more than once.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public AlmediaTask         Task         { get; }
public string              Timestamp    { get; }
public DateTimeOffset?     CompletedAt  { get; }
public AlmediaRewardPoints ActualReward { get; }

public AlmediaCompletedTask(AlmediaTask task, string timestamp, AlmediaRewardPoints actualReward);
```

| Property | Notes |
| - | - |
| `Task` | The completed task. |
| `Timestamp` | Raw ISO 8601 string. The time of the completion. |
| `CompletedAt` | Parsed UTC `DateTimeOffset?`. `null` when `Timestamp` is empty or not valid. |
| `ActualReward` | The reward this completion paid. It differs from `Task.Reward` when the reward decreased before completion, or when Freecash adjusted the credit. |

***

## `AlmediaRewardPoints`

Namespace: `AlmediaSDK` · sealed class

A balance or a reward in coins, with the display values the server supplied.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public long         Coins            { get; }
public AlmediaMoney InPlayerCurrency { get; }
public AlmediaMoney InUsd            { get; }

public AlmediaRewardPoints(long coins, AlmediaMoney inPlayerCurrency, AlmediaMoney inUsd);
```

| Property | Notes |
| - | - |
| `Coins` | The canonical amount. The money values are for display only. The value is signed. A reversal is negative. |
| `InPlayerCurrency` | The amount in the currency the server selected for the player. If this SDK version does not support that currency, the SDK substitutes the `InUsd` value and the `"USD"` code. |
| `InUsd` | The amount in USD. |

Each SDK version supports a closed set of player currencies. You can write your formatting against this list. This release supports `USD`, `EUR`, `GBP`, `CAD`, `AUD`, `PLN`, `CHF`, `KRW`, `JPY` and `SEK`. A new market needs a new SDK release.

***

## `AlmediaMoney`

Namespace: `AlmediaSDK` · sealed class

A coin amount in real money, for display only.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public decimal Amount   { get; }
public string  Currency { get; }

public AlmediaMoney(decimal amount, string currency);
```

| Property | Notes |
| - | - |
| `Amount` | An exact `decimal`. The SDK parses it from the wire string, independent of the device locale. The SDK never uses a `float` or a `double`. The scale from the server stays: `12.50` stays `12.50`. |
| `Currency` | The ISO 4217 code, in upper case. |

Every progress type compares by value, so `progress.Completed.Contains(completion.Task)` works and two snapshots with the same content are equal. `AlmediaMoney` compares numerically: `12.50` equals `12.5`.

The SDK does not format money. Format `Amount` with your own symbols, decimals and fonts:

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
var eur = new CultureInfo("de-DE");
label.text = money.Amount.ToString("N2", eur) + " " + money.Currency;   // "12,50 EUR"
```

***

## `AlmediaTaskCompletion`

Namespace: `AlmediaSDK` · sealed class

A task the server reports as completed. [`OnTaskCompleted`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediataskcompletion%3E-ontaskcompleted) delivers it.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public string               Id   { get; }
public AlmediaCompletedTask Task { get; }

public AlmediaTaskCompletion(string id, AlmediaCompletedTask task);
```

| Property | Notes |
| - | - |
| `Id` | The server-generated message id. A replay carries the same id. Deduplicate on it. |
| `Task` | The completion, with `ActualReward`. The task is not always in the current snapshot. |

***

## `AlmediaBalanceChange`

Namespace: `AlmediaSDK` · sealed class

A balance change the server reports. [`OnBalanceChanged`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediabalancechange%3E-onbalancechanged) delivers it.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public string              Id      { get; }
public AlmediaRewardPoints Balance { get; }
public AlmediaRewardPoints Change  { get; }

public AlmediaBalanceChange(string id, AlmediaRewardPoints balance, AlmediaRewardPoints change);
```

| Property | Notes |
| - | - |
| `Id` | The server-generated message id. A replay carries the same id. Deduplicate on it. |
| `Balance` | The balance after the change. It can differ from the current snapshot. |
| `Change` | The signed change. A reversal is negative. |

***

## `AlmediaPlacementType`

Namespace: `AlmediaSDK` · sealed class

Analytics tag passed to [`StartLinking(placement)`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-methods#static-void-startlinking-almediaplacementtype-placement). Only the static members below exist. Compare them with `==`. `ToString()` returns the member name.

| Member | Native string | Suggested context |
| - | - | - |
| `Popup` | `"popup"` | Default. Linking initiated from a modal popup. |
| `RewardHub` | `"reward_hub"` | Linking initiated from a rewards / store UI. |
| `Banner` | `"banner"` | Linking initiated from an in-game banner ad slot. |

Behaviorally identical - the difference is reflected only in analytics.

***

## `AlmediaLinkSource`

Namespace: `AlmediaSDK` · sealed class

Where a link popup open came from. [`ShowLink(source)`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-methods#static-void-showlink-almedialinksource-source) takes it, the popup reads it as `Source`, and the [`AlmediaLinkPopupController`](https://docs.almedia.dev/technical/api-reference/almedia/ui-components#almedialinkpopupcontroller) events carry it.

| Member | Description |
| - | - |
| `AlmediaLinkSource(string name)` | A source of kind `ShowLink`. A null or empty name reads as `custom`. |
| `AlmediaLinkSource(string name, object payload)` | The same, with an object of yours attached. |
| `static AlmediaLinkSource ShowLink` | The source of `ShowLink()` called without an argument. Name `show_link`, kind `ShowLink`. |
| `string Name` | The label as given. Never null or empty. |
| `AlmediaLinkSourceKind Kind` | What opened the popup. The SDK sets it; a source you create always reads `ShowLink`. |
| `object Payload` | The object you attached, or null. The SDK never reads, logs or sends it. |

Two sources are equal, with `==` and `Equals`, when their `Kind` and `Name` are equal. The payload takes no part. `ToString()` returns the name.

***

## `AlmediaLinkSourceKind`

Namespace: `AlmediaSDK` · sealed class

What opened the link popup, read from [`AlmediaLinkSource.Kind`](https://docs.almedia.dev/technical/api-reference/almedia/models#almedialinksource). Only the static members below exist. Compare them with `==`. `ToString()` returns the member name.

| Member | Meaning |
| - | - |
| `ShowLink` | The game called `ShowLink()` or `ShowLink(source)`, whatever the name. |
| `LinkButton` | The player tapped a `LinkButton` prefab. The name is the button's **Source Name**, `link_button` by default. |

***

## `AlmediaScreen`

Namespace: `AlmediaSDK` · sealed class

Identifies which SDK screen a lifecycle event is about. Delivered to [`OnScreenPresented`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediascreen%3E-onscreenpresented) and [`OnScreenDismissed`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediascreen-almediainappscreenresult%3E-onscreendismissed). Only the static members below exist. Compare them with `==`. `ToString()` returns the member name.

| Member | Native string | Meaning |
| - | - | - |
| `Linking` | `"linking"` | The account-linking flow shown in an in-app webview. System-browser linking is not reported. |
| `RewardHub` | `"reward_hub"` | The reward progression screen ([`ShowRewardHub()`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-methods#static-void-showrewardhub)). |
| `Offer` | `"offer"` | The offer screen ([`ShowOffer()`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-methods#static-void-showoffer)). |

An unrecognized screen string from native is logged as a warning and the callback is dropped - the events never fire with a garbage value.

***

## `AlmediaFeature`

Namespace: `AlmediaSDK` · sealed class

A part of the Link experience a game can declare it hides from its players, through [`AlmediaConfig.DisabledFeatures`](https://docs.almedia.dev/technical/api-reference/almedia/almediaconfig) or the settings asset. The backend enforces the declaration; the SDK only reports it and reacts to the status that comes back. Only the static members below exist; there is no constructor and no cast, so an undeclared value cannot be built. A `null` entry in `DisabledFeatures` is ignored. `ToString()` returns the wire name.

| Member | Wire name | Disabled means |
| - | - | - |
| `Linking` | `"linking"` | A not-linked player reads `NotAvailable` with reason [`Disabled`](https://docs.almedia.dev/technical/api-reference/almedia/models#almedianotavailablereason); `StartLinking()` fails through the existing status check. A linked player is untouched. |
| `RewardHub` | `"reward_hub"` | `CanShowRewardHub` is false on a `Linked` status; `ShowRewardHub()` is a no-op; the bundled button hides. |
| `Offer` | `"offer"` | `CanShowOffer` is false on a `Linked` status; `ShowOffer()` is a no-op. |
| `Notifications` | `"notifications"` | No Almedia notification reaches the game, in the SDK's UI or through `OnNotificationsReceived`. Reward grants are unaffected. |

Linking and the two screens are independent: hiding the entry point does not un-link anyone or close the hub to a player who linked earlier.

***

## `AlmediaInAppScreenResult`

Namespace: `AlmediaSDK` · abstract class

How an in-app screen was dismissed. Delivered to [`OnScreenDismissed`](https://docs.almedia.dev/technical/api-reference/almedia/almedia-events#static-event-action%3Calmediascreen-almediainappscreenresult%3E-onscreendismissed). Each result is a nested sealed class.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
public abstract class AlmediaInAppScreenResult : IEquatable<AlmediaInAppScreenResult>
{
    public sealed class Completed : AlmediaInAppScreenResult { public Completed(); }
    public sealed class Cancelled : AlmediaInAppScreenResult { public Cancelled(); }

    public sealed class Failed : AlmediaInAppScreenResult
    {
        public Failed(AlmediaError error);
        public AlmediaError Error { get; }
    }
}
```

| Result | Native string | Meaning |
| - | - | - |
| `Completed` | `"completed"` | The web client closed the screen through its JS bridge. |
| `Cancelled` | `"cancelled"` | The player closed the screen with the close/back button. |
| `Failed` | `"failed"` | The screen could not load. `Error` carries the detail. |

An unrecognized value from native is treated as `Cancelled` and logged. Test a result with a type pattern. Keep a `default` branch in a `switch`: a later version can add results.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
switch (result)
{
    case AlmediaInAppScreenResult.Completed _: break;
    case AlmediaInAppScreenResult.Cancelled _: break;
    case AlmediaInAppScreenResult.Failed failed: Debug.LogWarning(failed.Error.Message); break;
    default: break;
}
```

Results compare by value. `Failed` built with a `null` error carries an `Unknown` error.

***

## `AlmediaLogLevel`

Namespace: `AlmediaSDK` · sealed class

Severity levels for `OnLog`, ordered low → high: `Verbose`, `Debug`, `Info`, `Warning`, `Error`. Only these static members exist. Compare them with `==`, and order them with `<`, `<=`, `>` and `>=`. `ToString()` returns the member name.

```csharp theme={"theme":{"light":"github-light","dark":"night-owl"}}
Almedia.OnLog += (level, message) =>
{
    if (level >= AlmediaLogLevel.Warning)
        Debug.LogWarning(message);
};
```

***


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