Skip to main content

Unity SDK reference

The Aghanim Unity SDK that allows you to use the Checkout within both your Android and iOS apps.

Android. Default browser
Android. Default browser

Android. Default browser

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.

Editor and Standalone

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.

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}");
}
);
ParameterTypeRequiredDescription
configAghanimConfigYesSDK configuration. Set the SDK API key, and optionally MinLogLevel and Logger.
onSuccessActionNoCallback that is invoked once the SDK is ready to use.
onErrorAction<ApiError>NoCallback 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.

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}");
}
);
ParameterTypeRequiredDescription
orderIdstringYesUnique ID for the Order.
onSuccessAction<OrderRead>Yes if no errorCallback that is invoked on successful result.
onErrorAction<ApiError>Yes if no successCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels the call. See Cancellation.

Get unconsumed Orders

To know what Orders have been paid for but not granted yet, use the GetUnconsumedOrders method.

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
}
);
ParameterTypeRequiredDescription
onSuccessAction<UnconsumedOrdersResponse>Yes if no errorCallback that is invoked on successful result. Use response.Orders to access the array of order IDs.
onErrorAction<ApiError>Yes if no successCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels 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:

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}");
}
);
}

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:

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.

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
}
);
ParameterTypeRequiredDescription
orderIdstringYesUnique ID for the Order.
onSuccessActionYes if no errorCallback that is invoked on successful result.
onErrorAction<ApiError>Yes if no successCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels the call. See Cancellation.

When to use

Call ConsumeOrder after fetching unconsumed orders. A consumed Order is not returned by GetUnconsumedOrders again.

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}");
}
);
}

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.

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}");
}
);
ParameterTypeRequiredDescription
playerIdstringYesUnique ID for the player.
onSuccessActionNoCallback that is invoked on successful result.
onErrorAction<ApiError>NoCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels 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.

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}");
}
);
ParameterTypeRequiredDescription
onSuccessActionNoCallback that is invoked on successful result.
onErrorAction<ApiError>NoCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels 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.

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
}
);
ParameterTypeRequiredDescription
skusList<string>YesList of item SKUs to retrieve.
localeLocale?NoLocale for localization. Find the full list of supported locales in Checkout → Locales.
onSuccessAction<Item[]>Yes if no errorCallback that is invoked on successful result.
onErrorAction<ApiError>Yes if no successCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels 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.

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}");
}
);
ParameterTypeRequiredDescription
localeLocale?NoLocale for localization. Find the full list of supported locales in Checkout → Locales.
onSuccessAction<PricePointsResponse>Yes if no errorCallback that is invoked on successful result.
onErrorAction<ApiError>Yes if no successCallback that is invoked on failed result.
cancellationTokenCancellationTokenNoCancels 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.

var items = new List<CheckoutItem>
{
new CheckoutItem("CRS-82500")
};
ParameterTypeRequiredDescription
skustringYesItem SKU from Dashboard.
namestringNoItem name from Dashboard.
descriptionstringNoItem description from Dashboard.
imageUrlstringNoItem 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.

When the player has completed the payment, the SDK redirects them immediately to the deep link from backToGameUrl.

var redirectSettings = new RedirectSettings(
mode: RedirectMode.Immediate
);
ParameterTypeRequiredDescription
modeRedirectModeYesRedirect mode. Possible values: Immediate, Delayed, NoRedirect.
delaySecondsintYes if DelayedDelay in seconds. For Delayed mode, default is 5.

Create UI settings

To set the appearance mode for the Checkout, use the UiSettings method.

The SDK automatically detects and applies the appropriate appearance mode based on the system setting.

var uiSettings = new UiSettings(
mode: UiMode.Auto
);
ParameterTypeRequiredDescription
modeUiModeYesUI 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.

var checkoutParams = new CheckoutParams(
items: items,
backToGameUrl: "https://<YOUR_DOMAIN>/checkout-complete",
locale: "en"
);
ParameterTypeRequiredDescription
itemsIReadOnlyList<CheckoutItem>YesList of items. Copied on construction, so later changes to your list are not picked up.
metadataIReadOnlyDictionary<string, string>NoMetadata structured as “key-value” pairs for tracking purposes. Copied on construction.
localestringNoLocale for localization, as the Hub value in Checkout → Locales, for example en or pt-BR.
backToGameUrlstringNoDeep link URL to return the player to your app. Required for every launch mode except Android NativeUI(); see Configure deep links.
redirectSettingsRedirectSettingsNoPost-payment redirect behavior.
uiSettingsUiSettingsNoCheckout appearance settings.

Use Checkout launch mode

To launch the payment form, use the LaunchMode entity.

For Android and iOS, the In-app browser launch mode creates the seamless players’ experience via Android Custom Tabs and iOS SFSafariViewController.

LaunchMode.InternalBrowser

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.

For Android and iOS, the In-app browser launch mode creates the seamless players’ experience via Android Custom Tabs and iOS SFSafariViewController.

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
}
);
ParameterTypeRequiredDescription
checkoutParamsCheckoutParamsYesCheckout configuration.
launchModeLaunchModeYesLaunch mode for Checkout.
onSuccessAction<string>YesCallback invoked with Order ID on successful Checkout launch.
onErrorAction<ApiError>YesCallback invoked on failed Checkout launch.
cancellationTokenCancellationTokenNoCancels 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.

For Android and iOS, the In-app browser launch mode creates the seamless players' experience via Android Custom Tabs and iOS SFSafariViewController.

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
}
);
ParameterTypeRequiredDescription
orderIdstringYesID of the existing order to open.
launchModeLaunchModeYesLaunch mode for Checkout.
onSuccessAction<string>YesCallback invoked with Order ID on successful Checkout launch.
onErrorAction<ApiError>YesCallback invoked on failed Checkout launch.
cancellationTokenCancellationTokenNoCancels 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.

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.

warning

DebugMessage is a non-localized diagnostic string, present on every case. Log it, never show it to players.

Error reference

CaseExtra dataRaised when
CancelledThe CancellationToken you passed was cancelled.
NetworkConnectivity, DNS or a transport-layer failure.
TimeoutThe request did not complete in time.
NotAuthenticatedThe request carries no valid credentials.
NotAuthorizedAuthenticated, but not permitted to do this.
ServerCodeThe backend returned an error response.
NotFoundThe requested resource does not exist.
BadRequestThe backend rejected the request as malformed.
ValidationErrorsThe backend rejected one or more fields.
ConflictThe request conflicts with the current state, such as consuming an order twice.
RateLimitExceededToo many requests.
ServerUnavailableThe backend is temporarily unavailable.
UnknownTypeThe SDK could not classify the failure.
PlayerIdNotSetThe call needs a player ID and none is set.
NotInitializedInitialize has not completed successfully.
AlreadyInitializedInitialize was called a second time.
DisposedThe SDK instance was disposed.
UnsupportedThe operation is not available on this platform, such as LaunchMode.InternalBrowser in the Editor.
InvalidArgumentArgumentName, ReasonAn 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.

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
);
}
}

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.

Opt-in

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

What platforms does your Unity SDK support?

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]