Unity SDK reference
The Aghanim Unity SDK that allows you to use the Checkout within both your Android and iOS apps.
Integration
To integrate the SDK, see its prerequisites and the detailed instruction on Integrate → Unity.
Method reference
The SDK provides direct access to the Aghanim API through the Aghanim entity, in the AghanimSdk.Runtime.Api namespace.
Every method is asynchronous and reports its outcome through onSuccess and onError, invoked on the Unity main thread. Every method also takes an optional CancellationToken as its last parameter. See Error handling and Cancellation.
The API works in the Editor, in Standalone players and in WebGL; for development, not for production use. Only LaunchMode.DefaultBrowser is supported there.
Initialize
To initialize the SDK, use the Initialize method. Call it once per game process, on the Unity main thread, before any other SDK method.
- Callbacks
- UniTask
- C#
var config = new AghanimConfig("YOUR_SDK_API_KEY")
{
// Optional. Default is AghanimLogLevel.NONE
MinLogLevel = AghanimLogLevel.DEBUG
};
Aghanim.Initialize(
config,
onSuccess: () =>
{
// The SDK is ready. Make your first call from here
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to initialize: {error.DebugMessage}");
}
);
- C#
private async UniTask InitializeAsync()
{
var config = new AghanimConfig("YOUR_SDK_API_KEY")
{
// Optional. Default is AghanimLogLevel.NONE
MinLogLevel = AghanimLogLevel.DEBUG
};
var result = await Aghanim.InitializeAsync(config);
if (result.GetErrorOrNull() is { } error)
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to initialize: {error.DebugMessage}");
return;
}
// The SDK is ready. Make your first call from here
}
| Parameter | Type | Required | Description |
|---|---|---|---|
config | AghanimConfig | Yes | SDK configuration. Set the SDK API key, and optionally MinLogLevel and Logger. |
onSuccess | Action | No | Callback that is invoked once the SDK is ready to use. |
onError | Action<ApiError> | No | Callback that is invoked on failed result. |
A second Initialize leaves the first configuration in effect, reports ApiError.AlreadyInitialized and never invokes onSuccess.
Get Order
To get Order details, use the GetOrder method.
- Callbacks
- UniTask
- C#
Aghanim.GetOrder(
orderId: "order_123",
onSuccess: (order) =>
{
Debug.Log($"Order ID: {order.Id}");
Debug.Log($"Player ID: {order.PlayerId}");
Debug.Log($"Total price: {order.PriceMinorUnit} {order.Currency}");
},
onError: (error) =>
{
Debug.LogError($"Failed to get order: {error.DebugMessage}");
}
);
- C#
private async UniTask ShowOrderAsync(string orderId)
{
switch (await Aghanim.GetOrderAsync(orderId))
{
case ApiResult<OrderRead>.Success success:
var order = success.Value;
Debug.Log($"Order ID: {order.Id}");
Debug.Log($"Player ID: {order.PlayerId}");
Debug.Log($"Total price: {order.PriceMinorUnit} {order.Currency}");
break;
case ApiResult<OrderRead>.Failure failure:
Debug.LogError($"Failed to get order: {failure.Error.DebugMessage}");
break;
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | string | Yes | Unique ID for the Order. |
onSuccess | Action<OrderRead> | Yes if no error | Callback that is invoked on successful result. |
onError | Action<ApiError> | Yes if no success | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
Get unconsumed Orders
To know what Orders have been paid for but not granted yet, use the GetUnconsumedOrders method.
- Callbacks
- UniTask
- C#
Aghanim.GetUnconsumedOrders(
onSuccess: (response) =>
{
// Player has paid but not granted items from orders
var unconsumedOrderIds = response.Orders;
// TODO: Save order IDs for further consuming and granting
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to get unconsumed orders: {error.DebugMessage}");
// TODO: Handle error
}
);
- C#
private async UniTask CheckUnconsumedOrdersAsync()
{
switch (await Aghanim.GetUnconsumedOrdersAsync())
{
case ApiResult<UnconsumedOrdersResponse>.Success success:
// Player has paid but not granted items from orders
var unconsumedOrderIds = success.Value.Orders;
// TODO: Save order IDs for further consuming and granting
break;
case ApiResult<UnconsumedOrdersResponse>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to get unconsumed orders: {failure.Error.DebugMessage}");
// TODO: Handle error
break;
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
onSuccess | Action<UnconsumedOrdersResponse> | Yes if no error | Callback that is invoked on successful result. Use response.Orders to access the array of order IDs. |
onError | Action<ApiError> | Yes if no success | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
When to use
GetUnconsumedOrders and ConsumeOrder are designed for games without a dedicated server (serverless). They allow you to handle item granting entirely on the client side.
If your game has a server, use the item.add webhook instead. It lets your server control item granting directly. See Handle post-payment events on game server-side in the integration guide.
When to call GetUnconsumedOrders depends on the launch mode you use:
Default browser, In-app browser, WebView, Custom per platform with Native UI (Android)
For these modes, subscribe to the standard Unity callbacks OnApplicationFocus and OnApplicationPause, which fire when the player returns to the app after completing the payment:
- Callbacks
- UniTask
- C#
private void OnApplicationFocus(bool hasFocus)
{
if (hasFocus)
{
CheckUnconsumedOrders();
}
}
private void OnApplicationPause(bool isPaused)
{
if (!isPaused)
{
CheckUnconsumedOrders();
}
}
private void CheckUnconsumedOrders()
{
Aghanim.GetUnconsumedOrders(
onSuccess: (response) =>
{
foreach (var orderId in response.Orders)
{
ConsumeAndGrantOrder(orderId);
}
},
onError: (error) =>
{
Debug.LogError($"Failed to get unconsumed orders: {error.DebugMessage}");
}
);
}
- C#
private void OnApplicationFocus(bool hasFocus)
{
if (hasFocus)
{
CheckUnconsumedOrdersAsync().Forget();
}
}
private void OnApplicationPause(bool isPaused)
{
if (!isPaused)
{
CheckUnconsumedOrdersAsync().Forget();
}
}
private async UniTask CheckUnconsumedOrdersAsync()
{
switch (await Aghanim.GetUnconsumedOrdersAsync(destroyCancellationToken))
{
case ApiResult<UnconsumedOrdersResponse>.Success success:
foreach (var orderId in success.Value.Orders)
{
await ConsumeAndGrantOrderAsync(orderId);
}
break;
case ApiResult<UnconsumedOrdersResponse>.Failure failure:
Debug.LogError($"Failed to get unconsumed orders: {failure.Error.DebugMessage}");
break;
}
}
In-app browser and WebView (iOS)
On iOS, in addition to OnApplicationFocus / OnApplicationPause, the onViewClosed callback fires at the exact moment the player closes the view:
- C#
var launchMode = new LaunchMode(
android: AndroidLaunchMode.InAppBrowser(),
ios: IOSLaunchMode.InAppBrowser(
onViewClosed: (e) =>
{
// Earliest point to check order status on iOS
CheckUnconsumedOrders();
}
)
);
Consume paid Order
To mark a paid Order as handled, use the ConsumeOrder method. Consuming the same Order twice fails, so grant its items once the consume succeeds.
- Callbacks
- UniTask
- C#
Aghanim.ConsumeOrder(
orderId: orderId,
onSuccess: () =>
{
// Paid order is marked as consumed
Debug.Log($"Order consumed: {orderId}");
// TODO: Grant items in order to player
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to consume order: {error.DebugMessage}");
// TODO: Handle error
}
);
- C#
private async UniTask ConsumeOrderAsync(string orderId)
{
var result = await Aghanim.ConsumeOrderAsync(orderId);
if (result.GetErrorOrNull() is { } error)
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to consume order: {error.DebugMessage}");
// TODO: Handle error
return;
}
// Paid order is marked as consumed
Debug.Log($"Order consumed: {orderId}");
// TODO: Grant items in order to player
}
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | string | Yes | Unique ID for the Order. |
onSuccess | Action | Yes if no error | Callback that is invoked on successful result. |
onError | Action<ApiError> | Yes if no success | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
When to use
Call ConsumeOrder after fetching unconsumed orders. A consumed Order is not returned by GetUnconsumedOrders again.
- Callbacks
- UniTask
- C#
private void ConsumeAndGrantOrder(string orderId)
{
Aghanim.ConsumeOrder(
orderId: orderId,
onSuccess: () =>
{
Debug.Log($"Order consumed: {orderId}");
// TODO: Grant items to player
},
onError: (error) =>
{
Debug.LogError($"Failed to consume order: {error.DebugMessage}");
}
);
}
- C#
private async UniTask ConsumeAndGrantOrderAsync(string orderId)
{
var result = await Aghanim.ConsumeOrderAsync(orderId);
if (result.GetErrorOrNull() is { } error)
{
Debug.LogError($"Failed to consume order: {error.DebugMessage}");
return;
}
Debug.Log($"Order consumed: {orderId}");
// TODO: Grant items to player
}
Set player ID
To set the player ID for the current SDK instance, use the SetPlayerId method. The SDK uses the ID in all following method calls.
- Callbacks
- UniTask
- C#
Aghanim.SetPlayerId(
playerId: playerId,
onSuccess: () =>
{
// The player ID is in effect. Make the next call from here
CheckUnconsumedOrders();
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to set player ID: {error.DebugMessage}");
}
);
- C#
private async UniTask SignInAsync(string playerId)
{
var result = await Aghanim.SetPlayerIdAsync(playerId);
if (result.GetErrorOrNull() is { } error)
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to set player ID: {error.DebugMessage}");
return;
}
// The player ID is in effect. Make the next call from here
await CheckUnconsumedOrdersAsync();
}
| Parameter | Type | Required | Description |
|---|---|---|---|
playerId | string | Yes | Unique ID for the player. |
onSuccess | Action | No | Callback that is invoked on successful result. |
onError | Action<ApiError> | No | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
Clear player ID
To drop the player ID the SDK is holding, use the ClearPlayerId method. Calls that need a player ID report ApiError.PlayerIdNotSet until you set one again.
- Callbacks
- UniTask
- C#
Aghanim.ClearPlayerId(
onSuccess: () =>
{
// The player ID is cleared. Calls that need one now fail until you set it again
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to clear player ID: {error.DebugMessage}");
}
);
- C#
private async UniTask SignOutAsync()
{
var result = await Aghanim.ClearPlayerIdAsync();
if (result.GetErrorOrNull() is { } error)
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to clear player ID: {error.DebugMessage}");
return;
}
// The player ID is cleared. Calls that need one now fail until you set it again
}
| Parameter | Type | Required | Description |
|---|---|---|---|
onSuccess | Action | No | Callback that is invoked on successful result. |
onError | Action<ApiError> | No | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
Get items
To retrieve items with localized prices, use the GetItems method. The method returns items created in SKU Management → Items with prices localized based on the player's region.
The SKU list has no length limit. The SDK splits a large request into parallel batches, returns the items in the order you asked for them, and drops duplicate SKUs.
- Callbacks
- UniTask
- C#
Aghanim.GetItems(
skus: new List<string> { "your-item-sku" },
onSuccess: (items) =>
{
foreach (var item in items)
{
// Use item.Name, item.Price.Display, item.ImageUrl to populate your store
Debug.Log($"{item.Name}: {item.Price.Display}");
}
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to get items: {error.DebugMessage}");
// TODO: Handle error
}
);
- C#
private async UniTask LoadStoreAsync()
{
var skus = new List<string> { "your-item-sku" };
switch (await Aghanim.GetItemsAsync(skus))
{
case ApiResult<Item[]>.Success success:
foreach (var item in success.Value)
{
// Use item.Name, item.Price.Display, item.ImageUrl to populate your store
Debug.Log($"{item.Name}: {item.Price.Display}");
}
break;
case ApiResult<Item[]>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to get items: {failure.Error.DebugMessage}");
// TODO: Handle error
break;
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
skus | List<string> | Yes | List of item SKUs to retrieve. |
locale | Locale? | No | Locale for localization. Find the full list of supported locales in Checkout → Locales. |
onSuccess | Action<Item[]> | Yes if no error | Callback that is invoked on successful result. |
onError | Action<ApiError> | Yes if no success | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
Get price points
To retrieve the price points configured for your game, with amounts in the player's local currency, use the GetPricePoints method.
- Callbacks
- UniTask
- C#
Aghanim.GetPricePoints(
locale: Locale.En,
onSuccess: (response) =>
{
Debug.Log($"Local currency: {response.Context.LocalCurrency}");
foreach (var pricePoint in response.PricePoints)
{
Debug.Log($"{pricePoint.Id}: {pricePoint.LocalPrice.Display}");
}
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to get price points: {error.DebugMessage}");
}
);
- C#
private async UniTask LoadPricePointsAsync()
{
switch (await Aghanim.GetPricePointsAsync(Locale.En))
{
case ApiResult<PricePointsResponse>.Success success:
var response = success.Value;
Debug.Log($"Local currency: {response.Context.LocalCurrency}");
foreach (var pricePoint in response.PricePoints)
{
Debug.Log($"{pricePoint.Id}: {pricePoint.LocalPrice.Display}");
}
break;
case ApiResult<PricePointsResponse>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to get price points: {failure.Error.DebugMessage}");
break;
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
locale | Locale? | No | Locale for localization. Find the full list of supported locales in Checkout → Locales. |
onSuccess | Action<PricePointsResponse> | Yes if no error | Callback that is invoked on successful result. |
onError | Action<ApiError> | Yes if no success | Callback that is invoked on failed result. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
Create Checkout item
To create an item representation, use the CheckoutItem method. The item must already exist in SKU Management → Items, either created there or through the S2S API. Checkout rejects a SKU that is not in the game's catalog, and takes every price from the catalog; the client cannot set or override a price.
- C#
var items = new List<CheckoutItem>
{
new CheckoutItem("CRS-82500")
};
| Parameter | Type | Required | Description |
|---|---|---|---|
sku | string | Yes | Item SKU from Dashboard. |
name | string | No | Item name from Dashboard. |
description | string | No | Item description from Dashboard. |
imageUrl | string | No | Item image URL from Dashboard. |
Create redirect behavior
To choose the behavior of redirecting the player after they have completed the payment successfully, use the RedirectSettings method.
- Immediate
- Delayed
- No redirect
When the player has completed the payment, the SDK redirects them immediately to the deep link from backToGameUrl.
- C#
var redirectSettings = new RedirectSettings(
mode: RedirectMode.Immediate
);
When the player has completed the payment, the SDK shows the screen for the successful payment and then redirects the player to the deep link from backToGameUrl.
- C#
var redirectSettings = new RedirectSettings(
mode: RedirectMode.Delayed,
delaySeconds: 5
);
When the player has completed the payment, they stay on the screen for the successful payment. To exit it, they manually close it or navigate away. After, you should redirect them to the deep link from backToGameUrl by yourself.
- C#
var redirectSettings = new RedirectSettings(
mode: RedirectMode.NoRedirect
);
| Parameter | Type | Required | Description |
|---|---|---|---|
mode | RedirectMode | Yes | Redirect mode. Possible values: Immediate, Delayed, NoRedirect. |
delaySeconds | int | Yes if Delayed | Delay in seconds. For Delayed mode, default is 5. |
Create UI settings
To set the appearance mode for the Checkout, use the UiSettings method.
- Auto
- Dark
- Light
The SDK automatically detects and applies the appropriate appearance mode based on the system setting.
- C#
var uiSettings = new UiSettings(
mode: UiMode.Auto
);
The SDK forces dark mode appearance for the Checkout UI.
- C#
var uiSettings = new UiSettings(
mode: UiMode.Dark
);
The SDK forces light mode appearance for the Checkout UI.
- C#
var uiSettings = new UiSettings(
mode: UiMode.Light
);
| Parameter | Type | Required | Description |
|---|---|---|---|
mode | UiMode | Yes | UI mode. Possible values: Auto, Dark, Light. |
Create Checkout params
To create Checkout params, a representation of what the player sees on the payment form, use the CheckoutParams method.
- C#
var checkoutParams = new CheckoutParams(
items: items,
backToGameUrl: "https://<YOUR_DOMAIN>/checkout-complete",
locale: "en"
);
| Parameter | Type | Required | Description |
|---|---|---|---|
items | IReadOnlyList<CheckoutItem> | Yes | List of items. Copied on construction, so later changes to your list are not picked up. |
metadata | IReadOnlyDictionary<string, string> | No | Metadata structured as “key-value” pairs for tracking purposes. Copied on construction. |
locale | string | No | Locale for localization, as the Hub value in Checkout → Locales, for example en or pt-BR. |
backToGameUrl | string | No | Deep link URL to return the player to your app. Required for every launch mode except Android NativeUI(); see Configure deep links. |
redirectSettings | RedirectSettings | No | Post-payment redirect behavior. |
uiSettings | UiSettings | No | Checkout appearance settings. |
Use Checkout launch mode
To launch the payment form, use the LaunchMode entity.
- In-app browser
- Default browser
- WebView
- Custom per platform
For Android and iOS, the In-app browser launch mode creates the seamless players’ experience via Android Custom Tabs and iOS SFSafariViewController.
- C#
LaunchMode.InternalBrowser
For Android and iOS, the Default browser launch mode works in the player default browser. Use the mode when you want to redirect the player outside your app.
- C#
LaunchMode.DefaultBrowser
For Android and iOS, the WebView launch mode presents the Checkout inside a view the SDK owns, so the player never leaves your app. There is no LaunchMode.WebView shortcut; compose the mode per platform.
- C#
var launchMode = new LaunchMode(
android: AndroidLaunchMode.WebView(),
ios: IOSLaunchMode.WebView(
onViewClosed: (e) =>
{
// The player closed the WebView
// You can check order status and grant items if needed
}
)
);
You can use different launch modes for each platform.
- C#
var launchMode = new LaunchMode(
android: AndroidLaunchMode.NativeUI(),
ios: IOSLaunchMode.InAppBrowser()
);
| Parameter | Type | Required | Description |
|---|---|---|---|
android | AndroidLaunchMode | Yes | Launch mode for Android platform. Possible values: NativeUI(), InAppBrowser(), DefaultBrowser(), WebView(). |
ios | IOSLaunchMode | Yes | Launch mode for iOS platform. Possible values: InAppBrowser(), DefaultBrowser(), WebView(). |
On iOS, IOSLaunchMode.InAppBrowser() and IOSLaunchMode.WebView() accept an optional onViewClosed callback. It is invoked when the player closes the view. You can use it to check the order status and grant items when the player returns to the game.
- C#
var launchMode = new LaunchMode(
android: AndroidLaunchMode.InAppBrowser(),
ios: IOSLaunchMode.InAppBrowser(
onViewClosed: (e) =>
{
// The player closed the in-app browser
// You can check order status and grant items if needed
}
)
);
| Parameter | Type | Required | Description |
|---|---|---|---|
onViewClosed | Action<CheckoutViewClosedEvent> | No | Callback invoked when the view is closed on iOS. |
Start Checkout
To start the Checkout process, use the StartCheckout method. The method creates an order from the provided checkout params and opens the Checkout UI. On success, you receive the Order ID. On failure, you receive an ApiError with debug information.
- In-app browser
- Default browser
- Custom per platform
For Android and iOS, the In-app browser launch mode creates the seamless players’ experience via Android Custom Tabs and iOS SFSafariViewController.
- Callbacks
- UniTask
- C#
Aghanim.StartCheckout(
checkoutParams,
LaunchMode.InternalBrowser,
onSuccess: (orderId) =>
{
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {error.DebugMessage}");
// TODO: Show user-friendly error message to player
}
);
- C#
private async UniTask BuyAsync(CheckoutParams checkoutParams)
{
switch (await Aghanim.StartCheckoutAsync(checkoutParams, LaunchMode.InternalBrowser))
{
case ApiResult<string>.Success success:
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
Debug.Log($"Order created: {success.Value}");
break;
case ApiResult<string>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {failure.Error.DebugMessage}");
// TODO: Show user-friendly error message to player
break;
}
}
For Android and iOS, the Default browser launch mode works in the player default browser. Use the mode when you want to redirect the player outside your app.
- Callbacks
- UniTask
- C#
Aghanim.StartCheckout(
checkoutParams,
LaunchMode.DefaultBrowser,
onSuccess: (orderId) =>
{
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {error.DebugMessage}");
// TODO: Show user-friendly error message to player
}
);
- C#
private async UniTask BuyAsync(CheckoutParams checkoutParams)
{
switch (await Aghanim.StartCheckoutAsync(checkoutParams, LaunchMode.DefaultBrowser))
{
case ApiResult<string>.Success success:
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
Debug.Log($"Order created: {success.Value}");
break;
case ApiResult<string>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {failure.Error.DebugMessage}");
// TODO: Show user-friendly error message to player
break;
}
}
You can use different launch modes for each platform.
- Callbacks
- UniTask
- C#
Aghanim.StartCheckout(
checkoutParams,
launchMode,
onSuccess: (orderId) =>
{
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {error.DebugMessage}");
// TODO: Show user-friendly error message to player
}
);
- C#
private async UniTask BuyAsync(CheckoutParams checkoutParams)
{
switch (await Aghanim.StartCheckoutAsync(checkoutParams, launchMode))
{
case ApiResult<string>.Success success:
// Order is created and checkout has launched successfully
// TODO: Save order ID for further granting or tracking
Debug.Log($"Order created: {success.Value}");
break;
case ApiResult<string>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to launch Checkout: {failure.Error.DebugMessage}");
// TODO: Show user-friendly error message to player
break;
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
checkoutParams | CheckoutParams | Yes | Checkout configuration. |
launchMode | LaunchMode | Yes | Launch mode for Checkout. |
onSuccess | Action<string> | Yes | Callback invoked with Order ID on successful Checkout launch. |
onError | Action<ApiError> | Yes | Callback invoked on failed Checkout launch. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
A successful launch means the Checkout opened, not that the player paid. To find out whether the payment went through, use the item.add webhook, or Get unconsumed Orders if your game has no server.
Present Checkout
To present the Checkout UI for an existing order, use the PresentCheckout method. Use this when you have an order ID from server-to-server order creation or when resuming a previously abandoned checkout.
- In-app browser
- Default browser
- Custom per platform
For Android and iOS, the In-app browser launch mode creates the seamless players' experience via Android Custom Tabs and iOS SFSafariViewController.
- Callbacks
- UniTask
- C#
Aghanim.PresentCheckout(
orderId,
LaunchMode.InternalBrowser,
onSuccess: (orderId) =>
{
// Checkout has launched successfully for the existing order
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to present Checkout: {error.DebugMessage}");
// TODO: Show user-friendly error message to player
}
);
- C#
private async UniTask ResumeAsync(string orderId)
{
switch (await Aghanim.PresentCheckoutAsync(orderId, LaunchMode.InternalBrowser))
{
case ApiResult<string>.Success:
// Checkout has launched successfully for the existing order
break;
case ApiResult<string>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to present Checkout: {failure.Error.DebugMessage}");
// TODO: Show user-friendly error message to player
break;
}
}
For Android and iOS, the Default browser launch mode works in the player default browser. Use the mode when you want to redirect the player outside your app.
- Callbacks
- UniTask
- C#
Aghanim.PresentCheckout(
orderId,
LaunchMode.DefaultBrowser,
onSuccess: (orderId) =>
{
// Checkout has launched successfully for the existing order
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to present Checkout: {error.DebugMessage}");
// TODO: Show user-friendly error message to player
}
);
- C#
private async UniTask ResumeAsync(string orderId)
{
switch (await Aghanim.PresentCheckoutAsync(orderId, LaunchMode.DefaultBrowser))
{
case ApiResult<string>.Success:
// Checkout has launched successfully for the existing order
break;
case ApiResult<string>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to present Checkout: {failure.Error.DebugMessage}");
// TODO: Show user-friendly error message to player
break;
}
}
You can use different launch modes for each platform.
- Callbacks
- UniTask
- C#
Aghanim.PresentCheckout(
orderId,
launchMode,
onSuccess: (orderId) =>
{
// Checkout has launched successfully for the existing order
},
onError: (error) =>
{
// Log debug information for troubleshooting
Debug.LogError($"Failed to present Checkout: {error.DebugMessage}");
// TODO: Show user-friendly error message to player
}
);
- C#
private async UniTask ResumeAsync(string orderId)
{
switch (await Aghanim.PresentCheckoutAsync(orderId, launchMode))
{
case ApiResult<string>.Success:
// Checkout has launched successfully for the existing order
break;
case ApiResult<string>.Failure failure:
// Log debug information for troubleshooting
Debug.LogError($"Failed to present Checkout: {failure.Error.DebugMessage}");
// TODO: Show user-friendly error message to player
break;
}
}
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | string | Yes | ID of the existing order to open. |
launchMode | LaunchMode | Yes | Launch mode for Checkout. |
onSuccess | Action<string> | Yes | Callback invoked with Order ID on successful Checkout launch. |
onError | Action<ApiError> | Yes | Callback invoked on failed Checkout launch. |
cancellationToken | CancellationToken | No | Cancels the call. See Cancellation. |
Error handling
Every onError callback receives an ApiError, a closed hierarchy in the AghanimSdk.Runtime.Api.Result namespace. Branch on the case rather than parsing a message.
- C#
private void OnError(ApiError error)
{
switch (error)
{
case ApiError.Cancelled:
// The call was cancelled; nothing to report to the player
return;
case ApiError.Network:
case ApiError.Timeout:
case ApiError.ServerUnavailable:
ShowRetryPrompt();
break;
case ApiError.NotAuthenticated:
case ApiError.NotAuthorized:
ReAuthenticate();
break;
case ApiError.Server server:
Debug.LogError($"HTTP {server.Code}: {server.DebugMessage}");
break;
case ApiError.InvalidArgument invalidArgument:
Debug.LogError($"{invalidArgument.ArgumentName} is {invalidArgument.Reason}");
break;
default:
Debug.LogError(error.DebugMessage);
break;
}
}
The hierarchy is closed, but the compiler does not treat it as exhaustive, so always keep a default branch.
DebugMessage is a non-localized diagnostic string, present on every case. Log it, never show it to players.
Error reference
| Case | Extra data | Raised when |
|---|---|---|
Cancelled | The CancellationToken you passed was cancelled. | |
Network | Connectivity, DNS or a transport-layer failure. | |
Timeout | The request did not complete in time. | |
NotAuthenticated | The request carries no valid credentials. | |
NotAuthorized | Authenticated, but not permitted to do this. | |
Server | Code | The backend returned an error response. |
NotFound | The requested resource does not exist. | |
BadRequest | The backend rejected the request as malformed. | |
Validation | Errors | The backend rejected one or more fields. |
Conflict | The request conflicts with the current state, such as consuming an order twice. | |
RateLimitExceeded | Too many requests. | |
ServerUnavailable | The backend is temporarily unavailable. | |
Unknown | Type | The SDK could not classify the failure. |
PlayerIdNotSet | The call needs a player ID and none is set. | |
NotInitialized | Initialize has not completed successfully. | |
AlreadyInitialized | Initialize was called a second time. | |
Disposed | The SDK instance was disposed. | |
Unsupported | The operation is not available on this platform, such as LaunchMode.InternalBrowser in the Editor. | |
InvalidArgument | ArgumentName, Reason | An argument was missing, blank, empty or unusable. |
Cancellation
Every method takes an optional CancellationToken as its last parameter. Tie it to the lifetime of the object making the call, so a scene teardown does not leave a callback pointing at a destroyed object.
- Callbacks
- UniTask
- C#
public class StorePanel : MonoBehaviour
{
private void OnEnable()
{
Aghanim.GetItems(
skus: new List<string> { "your-item-sku" },
onSuccess: (items) => Render(items),
onError: OnError,
// Unity cancels this token when the object is destroyed
cancellationToken: destroyCancellationToken
);
}
}
- C#
public class StorePanel : MonoBehaviour
{
private void OnEnable()
{
LoadStoreAsync().Forget();
}
private async UniTask LoadStoreAsync()
{
// Unity cancels this token when the object is destroyed
var result = await Aghanim.GetItemsAsync(
skus: new List<string> { "your-item-sku" },
cancellationToken: destroyCancellationToken
);
if (result is ApiResult<Item[]>.Success success)
{
Render(success.Value);
}
}
}
A token that is already cancelled skips the call. Otherwise onError receives ApiError.Cancelled once the cancellation is confirmed, or the real outcome if the operation finished first.
Async API
Every method on this page has a UniTask counterpart, shown in the UniTask tab of each example: InitializeAsync, SetPlayerIdAsync, ClearPlayerIdAsync, StartCheckoutAsync, PresentCheckoutAsync, GetOrderAsync, GetPricePointsAsync, GetItemsAsync, GetUnconsumedOrdersAsync and ConsumeOrderAsync.
The async API is compiled only when UniTask 2.5.10 or newer is installed. UniTask is not a dependency of the SDK package, so install it yourself; without it, these methods do not exist and the callback API is unaffected.
Each method returns UniTask<ApiResult<T>>, where ApiResult<T> is either Success carrying a Value or Failure carrying an Error. Operations that return nothing use ApiResult<Unit>.
Match on the case to use the value, or call GetErrorOrNull(), which returns the ApiError of a failure and null for a success, to keep an early return short.
The async methods take the CancellationToken as their last parameter, in place of the callbacks. StartCheckoutAsync and PresentCheckoutAsync take the launch mode as an optional parameter, defaulting to LaunchMode.Default.
They are safe to call from any thread and always complete on the Unity main thread. They never throw for an API failure; the failure arrives as ApiResult<T>.Failure.
FAQ
The Unity SDK ships for both iOS and Android.
The API also works in the Editor, in Standalone players and in WebGL, where only LaunchMode.DefaultBrowser is supported; for development, not for production use.
Need help?
Contact our integration team at [email protected]













