Balancy JavaScript API¶
View instance context¶
New View scripts must pass a runtime instanceId, not a configuration unnyId / unnyIdGameEvent. Obtain it from the EventInfo, OfferInfo, or OfferGroupInfo passed to your root script's init(info). When instantiating a child card, pass that card's own info to its init(info); do not borrow the parent View owner.
Explicit IDs are strict: unknown IDs, configuration IDs and invalid values do not fall back to the global owner. Event operations require an event instance; an offer instance is not an event instance. Custom event info supports event, offer and group instances and keeps their data separate.
| Method | New signature |
|---|---|
| Tasks | getTasks(instanceId) |
| Activate/deactivate tasks | activateTasks(taskIds, instanceId), deactivateTasks(taskIds, instanceId) |
| Battle Pass | getBattlePassConfig(instanceId), getBattlePassProgress(instanceId) |
| Battle Pass reward | claimBattlePassReward(lineId, index, instanceId) |
| Custom event info | getCustomEventInfo(instanceId), setCustomEventInfo(data, instanceId) |
| Stop event | stopEventManually(cooldown, instanceId); pass -1 for the configured cooldown |
| Offer purchase | buyOffer(instanceId) |
| Group purchase | buyGroupOffer(instanceId, index), canBuyGroupOffer(index, instanceId) |
| Timer | await createTimer(instanceId) |
Only the context argument changes. Task IDs in taskIds / claimTaskReward(taskId), reward line IDs, product IDs and getCustomDocumentInfo(unnyId) / setCustomDocumentInfo(unnyId, data) retain their existing meanings. These bridge APIs are JavaScript APIs inside the View on both Unity and web; they do not change the host C# API.
Examples below use eventInfo, offerInfo and offerGroupInfo for the corresponding runtime info objects supplied to init. A matching updated native SDK and bridge are required.
Overview¶
The balancy namespace provides access to backend data, user profiles, purchases, and platform-specific functionality. All methods are available globally in your View JavaScript.
Namespace¶
All Balancy methods and classes are under the balancy global object:
balancy.getSystemProfileValue('GeneralInfo.Level')
balancy.closeView('Purchase completed')
balancy.ElementsManager.instantiate(element)
DOM & Element Queries¶
balancy.findDomElement(dataId, parentElement?)¶
Finds an element with the specified data-id attribute.
Parameters:
dataId(string): The data-id value to search forparentElement(HTMLElement, optional): Parent element to search within (defaults to document)
Returns: HTMLElement | null
Example:
const headerElement = balancy.findDomElement('window-header');
const button = balancy.findDomElement('claim-button', headerElement);
balancy.setImage(element, sprite)¶
Sets an image on an HTML element using a Balancy sprite object.
Parameters:
element(HTMLElement): Target element (IMG tag or element with background)sprite(object): Sprite object with id property
Example:
const iconElement = document.getElementById('reward-icon');
balancy.setImage(iconElement, reward.item.unnyIcon);
Profile & Data Access¶
balancy.getSystemProfileValue(path)¶
Retrieves a value from the system profile (UnnyProfile).
Parameters:
path(string): Dot-separated path to the desired value
Returns: Promise<any>
Example:
const playerLevel = await balancy.getSystemProfileValue('GeneralInfo.Level');
//playerLevel = 5
const generalInfo = await balancy.getSystemProfileValue('GeneralInfo');
//generalInfo = { level: 5, session: 68, country: "CY", ... }
balancy.getProfileValue(profile, path)¶
Retrieves a value from a specific custom profile.
Parameters:
profile(string): Profile namepath(string): Dot-separated path to the desired value
Returns: Promise<any>
Example:
const coins = await balancy.getProfileValue('PlayerData', 'Currency.Coins');
balancy.getDocumentValue(id, depth)¶
Retrieves a document from Balancy with specified depth.
Parameters:
id(string): Document IDdepth(number): Depth of nested objects to fetch (default: 3)
Returns: Promise<object>
Example:
const config = await balancy.getDocumentValue('245', 3);
console.info(config);
Offers & Shops¶
balancy.getActiveOffers(depth?)¶
Retrieves the list of all active offers.
Parameters:
depth(number, optional): How deep to extract nested objects (default: 3)
Returns: Promise<OfferInfo[]>
Example:
const offers = await balancy.getActiveOffers();
// offers = [{ instanceId: "...", gameOffer: {...}, ... }]
balancy.getActiveGroupOffers(depth?)¶
Retrieves the list of all active group offers.
Parameters:
depth(number, optional): How deep to extract nested objects (default: 3)
Returns: Promise<OfferGroupInfo[]>
Example:
const groupOffers = await balancy.getActiveGroupOffers();
balancy.canBuyGroupOffer(index, instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Checks if a group offer can be purchased.
Parameters:
index(number): Offer index within the group
Returns: Promise<boolean>
Example:
const canBuy = await balancy.canBuyGroupOffer(0, offerGroupInfo.instanceId);
document.getElementById('buy-button').disabled = !canBuy;
balancy.getActiveShopInfo()¶
Retrieves the shop the player currently has active, together with its pages, slots and store items. Prefer this over reading the profile and then asking for the shop by id — it is a single request.
Returns: Promise<GameShop|null> — null when no shop is active, which is a
normal state and not an error.
Example:
const shop = await balancy.getActiveShopInfo();
for (const pageInfo of shop?.activePages ?? []) {
console.log(`Page: ${pageInfo.page?.name}`);
for (const slotInfo of pageInfo.activeSlots ?? []) {
const storeItem = slotInfo.slot?.storeItem;
console.log(` ${storeItem?.name} — ${storeItem?.price?.product?.price}`);
}
}
References are already resolved, so page, slot and storeItem arrive as
objects — no extra getDocumentValue() calls needed.
balancy.getShopInfo(shopConfig)¶
Same as above, but for a specific shop rather than the active one. Use it when the view already knows which shop it renders.
Parameters:
shopConfig(object): Shop document — only itsunnyIdis used
Returns: Promise<GameShop>
Example:
const shop = await balancy.getShopInfo({ unnyId: '412' });
Purchases¶
balancy.buyOffer(instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Purchases the offer selected by its runtime instanceId.
Returns: Promise<PurchaseResult>
Example:
try {
const result = await balancy.buyOffer(offerInfo.instanceId);
console.log('Purchase successful:', result);
} catch (error) {
console.error('Purchase failed:', error);
}
balancy.buyGroupOffer(instanceId, index)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Purchases a specific offer from a group.
Parameters:
index(number): Offer index within the group
Returns: Promise<PurchaseResult>
Example:
const result = await balancy.buyGroupOffer(offerGroupInfo.instanceId, 0);
balancy.buyShopSlot(slotId)¶
Purchases a shop slot.
Parameters:
slotId(string): The slot identifier
Returns: Promise<PurchaseResult>
Example:
const result = await balancy.buyShopSlot('slot-123');
balancy.getProductInfo(product)¶
Gets IAP product information from the platform store.
Parameters:
product(object): Product document
Returns: Promise<ProductInfo>
Example:
const productInfo = await balancy.getProductInfo(price.product);
console.log(productInfo.LocalizedPriceString); // "$4.99"
Resource Management¶
balancy.haveEnoughResources(storeItem)¶
Checks if the player has enough resources to purchase a store item.
Parameters:
storeItem(object): StoreItem document
Returns: Promise<boolean>
Example:
const canAfford = await balancy.haveEnoughResources(storeItem);
if (!canAfford) {
button.disabled = true;
button.classList.add('insufficient-funds');
}
balancy.getInventoryInfo(depth?)¶
Retrieves the whole inventory — currencies, items and event items — in one call.
Use it whenever you need to list what the player owns; getInventoryItemsCount()
only answers for an item you can already name.
Parameters:
depth(number, optional): How much of each item's configuration to include (default: 0).0returns item ids only,1includes the item document itself, and each further level expands one more level of its references. Anything above0saves you agetDocumentValue()call per item.
Returns: Promise<InventoryInfo>
Example:
const inventory = await balancy.getInventoryInfo(1);
for (const slot of inventory.items) {
if (!slot.unnyIdItem)
continue; // empty slot
console.log(`${slot.item?.name} x${slot.amount}`);
}
Each list contains every slot, including empty ones, because a slot's
position is meaningful and an empty slot can still be reserved for a specific
item. Filter on unnyIdItem when you only care about the contents.
A slot looks like this:
{
slotIndex: 0, // position in the inventory
unnyIdItem: '26', // null for an empty slot
amount: 7, // negative means an unlimited amount
created: 1756900000, // absent on an empty slot
updated: 1756900120, // absent on an empty slot
unnyIdAcceptableItem: null, // item this slot is reserved for, if any
item: { /* ... */ } // only when depth > 0
}
balancy.getInventoryItemsCount(itemId)¶
Gets the count of an inventory item.
Parameters:
itemId(string): Item identifier
Returns: Promise<number>
Example:
const coinCount = await balancy.getInventoryItemsCount('coins');
console.log(`Player has ${coinCount} coins`);
balancy.addInventoryItems(itemId, amount)¶
Adds items to player inventory.
Parameters:
itemId(string): Item identifieramount(number): Amount to add
Returns: Promise<void>
Example:
await balancy.addInventoryItems('gems', 100);
balancy.removeInventoryItems(itemId, amount)¶
Removes items from player inventory.
Parameters:
itemId(string): Item identifieramount(number): Amount to remove
Returns: Promise<void>
Example:
const currentCount = await balancy.getInventoryItemsCount('coins');
if (currentCount >= 50) {
await balancy.removeInventoryItems('coins', 50);
}
Localization¶
balancy.getLocalizedText(key)¶
Gets localized text for the specified key.
Parameters:
key(string): Localization key
Returns: Promise<string>
Example:
const welcomeText = await balancy.getLocalizedText('welcome_message');
document.getElementById('title').textContent = welcomeText;
balancy.getImageUrl(id)¶
Gets the URL for an image asset.
Parameters:
id(string): Image asset ID
Returns: Promise<string>
Example:
const imageUrl = await balancy.getImageUrl('123');
document.getElementById('icon').src = imageUrl;
View Control¶
balancy.closeView(source)¶
Closes the current view.
Parameters:
source(string): Reason for closing (for debugging)
Example:
balancy.closeView('Purchase completed');
balancy.closeView('User clicked close');
balancy.sendIsReady()¶
Notifies the SDK that the view is ready to be shown.
Example:
function main() {
balancy.delayIsReady();
// Load async data...
await loadData();
balancy.sendIsReady();
}
window.addEventListener('balancy-ready', main, { once: true });
balancy.delayIsReady()¶
Delays the automatic ready signal, giving you control over when the view is shown.
Example:
balancy.delayIsReady();
// Perform async initialization
await initializeView();
// Signal ready when done
balancy.sendIsReady();
balancy.setEmergencyExitEnabled(enabled)¶
Enables or disables the emergency exit button — a red close button that appears when the user triple-taps (or triple-clicks on desktop) anywhere on the view.
Parameters:
enabled(boolean):trueto allow triple-tap emergency exit (default),falseto disable it
Returns: Promise<{ status: string }>
Example:
// Disable the emergency exit — your view has its own close button
balancy.setEmergencyExitEnabled(false);
// Re-enable the emergency exit
balancy.setEmergencyExitEnabled(true);
The setting is persistent: if called before a view is open, it is applied when the next view loads.
For the SDK-side equivalent, see Emergency Exit Button.
Battle Pass¶
balancy.getBattlePassConfig(instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Gets the configuration for the current battle pass.
Returns: Promise<BattlePassConfig>
Example:
const config = await balancy.getBattlePassConfig(eventInfo.instanceId);
console.log('Scores required:', config.scores);
console.log('Reward lines:', config.rewards);
Response Structure:
{
unnyId: "995",
name: "KEY_SEASON_PASS_NAME",
scores: [10, 20, 30, 40, 50, 60], // XP required for each level
rewards: [
{
unnyId: "1007",
name: "Free Track",
rewards: [/* ItemWithAmount objects */]
}
]
}
balancy.getBattlePassProgress(instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Gets the current player's battle pass progress.
Returns: Promise<BattlePassProgress>
Example:
const progress = await balancy.getBattlePassProgress(eventInfo.instanceId);
console.log('Current level:', progress.level);
console.log('Current XP:', progress.scores);
Response Structure:
{
level: 1,
scores: 15,
finished: false,
progressInfo: [
{
progress: [1, 0, 0, 0, 0, 0], // 0=locked, 1=available, 2=claimed
available: true,
unnyIdReward: "1007"
}
]
}
balancy.claimBattlePassReward(lineId, index, instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Claims a battle pass reward.
Parameters:
lineId(string): Reward line IDindex(number): Level index to claim
Returns: Promise<boolean>
Example:
const success = await balancy.claimBattlePassReward('1007', 0, eventInfo.instanceId);
if (success) {
console.log('Reward claimed successfully!');
}
Ads¶
balancy.watchRewardedAd(callback)¶
Triggers a rewarded ad display.
Parameters:
callback(function): Function that receives boolean indicating success
Returns: Promise<void>
Example:
balancy.watchRewardedAd((success) => {
if (success) {
console.log('Ad watched successfully!');
grantReward();
} else {
console.log('Ad was not watched.');
}
});
balancy.getRewardedAdsWatchedForStoreItem(storeItem)¶
Gets the count of rewarded ads watched for a specific store item.
Parameters:
storeItem(object): StoreItem document
Returns: Promise<number>
Example:
const adsWatched = await balancy.getRewardedAdsWatchedForStoreItem(storeItem);
console.log(`Watched ${adsWatched} ads for this item`);
Tasks & Events¶
balancy.getTasks(instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Gets the list of active tasks.
Returns: Promise<Task[]>
Example:
const tasks = await balancy.getTasks(eventInfo.instanceId);
for (const task of tasks) {
console.log(task.name, task.status);
}
balancy.claimTaskReward(taskId)¶
Claims a task reward.
Parameters:
taskId(string): Task identifier
Returns: Promise<boolean>
Example:
const success = await balancy.claimTaskReward('daily-quest-1');
balancy.restoreFailedTask(task)¶
Restores a failed task (e.g., for win streak recovery).
Parameters:
task(object): The task object withstatus === balancy.TaskStatus.Failed
Returns: Promise<boolean>
Example:
const tasks = await balancy.getTasks(eventInfo.instanceId);
const failedTask = tasks.find(t => t.status === balancy.TaskStatus.Failed);
if (failedTask) {
const restored = await balancy.restoreFailedTask(failedTask);
console.log('Task restored:', restored);
}
balancy.activateTasks(taskIds, instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Activates tasks for an event.
Parameters:
taskIds(string[]): Array of task IDs
Returns: Promise<Task[]>
Example:
const tasks = await balancy.activateTasks(['quest-1', 'quest-2'], eventInfo.instanceId);
balancy.deactivateTasks(taskIds, instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Deactivates tasks.
Parameters:
taskIds(string[]): Array of task IDs
Returns: Promise<void>
Example:
await balancy.deactivateTasks(['quest-1', 'quest-2'], eventInfo.instanceId);
Custom Event & Document Info¶
Store arbitrary JSON data associated with events or documents. Data persists in the player's profile and syncs with the cloud. For the full SDK API (C#/TypeScript), see Custom Info in Configs & Profiles.
balancy.getCustomEventInfo(instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Gets custom data for the current event instance. Pass the runtime instanceId explicitly.
Returns: Promise<any> - Parsed JSON object, or {} if no data set
Example:
const eventData = await balancy.getCustomEventInfo(eventInfo.instanceId);
console.log('Event progress:', eventData.progress);
balancy.setCustomEventInfo(data, instanceId)¶
Context parameter: instanceId (string) — runtime instance ID; configuration unnyId is not accepted.
Saves custom data for the current event instance. The object is JSON-serialized before storage.
Parameters:
data(any): Data to save (will be JSON serialized)
Returns: Promise<void>
Example:
await balancy.setCustomEventInfo({
started: true,
progress: 50,
lastCheckpoint: 'level-3'
}, eventInfo.instanceId);
balancy.getCustomDocumentInfo(unnyId)¶
Gets custom data for a specific CMS document.
Parameters:
unnyId(string): The document's UnnyId
Returns: Promise<any> - Parsed JSON object, or {} if no data set
Example:
const data = await balancy.getCustomDocumentInfo('some-unny-id');
console.log('Document metadata:', data);
balancy.setCustomDocumentInfo(unnyId, data)¶
Saves custom data for a specific CMS document. The object is JSON-serialized before storage.
Parameters:
unnyId(string): The document's UnnyIddata(any): Data to save (will be JSON serialized)
Returns: Promise<void>
Example:
await balancy.setCustomDocumentInfo('some-unny-id', {
favorited: true,
notes: 'Player marked this item'
});
Custom Messages¶
Balancy provides two-way communication between your game code and Views. For complete documentation on custom messages including SDK-side setup, see Working with Views - Custom Messages.
balancy.sendCustomMessage(sender, params)¶
Send a custom message from JavaScript to your game code and receive a response.
Parameters:
sender(string): Message identifierparams(object): Data to send
Returns: Promise<any> - Response from game code
Example:
balancy.sendCustomMessage('my_button', {
param: 'myParam',
value: 42
}).then(response => {
console.info("Custom message response:", response);
}).catch(error => {
console.error("Custom message error:", error);
});
Default Response:
{
"status": "ok"
}
SDK Setup:
To intercept and respond to custom messages, see Custom Messages Documentation.
balancy.subscribeToCustomMessages(callback)¶
Subscribe to custom messages broadcast from the game.
Parameters:
callback(function): Handler function that receives message data
Returns: function - Unsubscribe function
Example:
// Method 1: Subscribe with callback (recommended)
const unsubscribe = balancy.subscribeToCustomMessages((data) => {
console.info('Received custom message:', data);
if (data.action === 'greeting') {
console.log('Message:', data.message);
}
});
// Unsubscribe later
unsubscribe();
// Method 2: Listen to DOM event
window.addEventListener('balancy-custom-message', (event) => {
console.log('Received custom message:', event.detail);
});
SDK Setup:
To send messages from your game to Views, see Broadcasting Messages Documentation.
Formatting Utilities¶
balancy.formatTime(seconds)¶
Formats time duration into a human-readable string.
Parameters:
seconds(number): Duration in seconds
Returns: string
Example:
const formatted = balancy.formatTime(7200);
// Returns: "2h"
const formatted2 = balancy.formatTime(86400);
// Returns: "1d"
const formatted3 = balancy.formatTime(125);
// Returns: "02:05"
balancy.createTimer(instanceId)¶
Creates an independent countdown for an active event, offer, or offer group. Battle Pass events use the same API. Pass the runtime instanceId from EventInfo, OfferInfo, or OfferGroupInfo, not a configuration unnyId. The SDK resolves the type automatically; this API never falls back to the View owner.
Returns: Promise<ViewTimer>.
timer.instanceId: the instance this timer belongs to.timer.getTimeLeft(): synchronous remaining whole seconds, rounded up and clamped to0;nullmeans no time limit.await timer.refresh(): fetch a new snapshot, for example after an event extension or returning from a long background pause. Concurrent refreshes share one request. A failed refresh rejects and keeps the previous snapshot.
Creation makes one native request. Reads count down locally from the received snapshot using a monotonic clock; they do not contact the SDK. Transport time is not subtracted from the snapshot. The timer does not automatically track event changes or removal. Refresh rejects if the instance no longer exists; invalid/empty IDs and unsupported native SDK versions also reject.
No intervals or subscriptions are created, and no dispose() is needed. In persistent mode, refreshing a timer from a disposed View rejects. Create a new timer for the next View. Use a matching native SDK and bridge build that support this API.
class OfferTimer extends balancy.ElementBehaviour {
// @serialize {element}
timerText = null;
timer = null;
async init(offerInfo) {
this.contextInfo = offerInfo;
this.timer = await balancy.createTimer(this.contextInfo.instanceId);
}
update() {
if (!this.timer) return;
const seconds = this.timer.getTimeLeft();
this.timerText.element.textContent = seconds === null
? '' : balancy.formatTime(seconds);
}
}
For an event or group, pass eventInfo.instanceId or offerGroupInfo.instanceId instead. Each instantiated card owns its own timer, so a shop can display several independent countdowns.
balancy.formatDataTemplate(formatStr, data)¶
Formats a template string with data values. Supports nested object access and automatic document resolution.
Parameters:
formatStr(string): Template string with{path}placeholdersdata(object): Data object
Returns: Promise<string>
Example - Basic:
const template = "You have {currency.coins} coins and level {level}";
const data = { currency: { coins: 100 }, level: 5 };
const result = await balancy.formatDataTemplate(template, data);
// Returns: "You have 100 coins and level 5"
Example - Document Resolution:
// If data.gameOffer is null but data.unnyIdGameOffer exists,
// the method automatically fetches the document
const template = "{gameOffer.name}";
const data = {
gameOffer: null,
unnyIdGameOffer: "1188"
};
const result = await balancy.formatDataTemplate(template, data);
// Returns: "DEFAULT/offer_name_key"
balancy.formatItemCount(itemWithAmount, options)¶
Formats an item count based on type (currency, time, regular).
Parameters:
itemWithAmount(object): ItemWithAmount documentoptions(object): Formatting options
Returns: { text: string, isCurrency: boolean, isDuration: boolean }
Example:
const result = balancy.formatItemCount(item, {
timeFormat: 2, // LocalizedCompact
currencyFormat: 0, // Plain
regularItemFormat: 2, // WithPrefix
timePrecision: 0 // Auto
});
console.log(result.text); // "x50" or "100" or "5h 32m"
balancy.formatItemsCount(itemWithAmount, includePrefix) 🗑️ OBSOLETE¶
⚠️ This method is obsolete. Use balancy.formatItemCount() instead for more control over formatting options.
Formats an item count based on type (currency, time, regular).
Parameters:
itemWithAmount(object): ItemWithAmount documentincludePrefix(boolean): Whether to include "x" prefix for regular items
Returns: { text: string, isCurrency: boolean, isDuration: boolean }
Example:
// ⚠️ Obsolete - use formatItemCount() instead
const format = balancy.formatItemsCount(reward, true);
console.log(format.text); // "x50" or "100" or "5h 32m"
// ✓ Recommended: Use formatItemCount() for better control
const result = balancy.formatItemCount(item, {
timeFormat: 2,
currencyFormat: 0,
regularItemFormat: 2,
timePrecision: 0
});
balancy.shortenCount(count)¶
Shortens large numbers with K/M/B suffixes.
Parameters:
count(number): Number to shorten
Returns: string
Example:
balancy.shortenCount(1500); // "1.5K"
balancy.shortenCount(1000000); // "1M"
balancy.shortenCount(500); // "500"
balancy.formatString(template, ...values)¶
Formats a template string with indexed placeholders.
Parameters:
template(string): Template with{0},{1}, etc....values(any[]): Values to insert
Returns: string
Example:
const message = balancy.formatString(
'You earned {0} coins and {1} XP!',
500,
150
);
// Returns: "You earned 500 coins and 150 XP!"
balancy.itemHasDecayEffect(item)¶
Checks if an item has a decay/time-limited effect.
Parameters:
item(object): Item document
Returns: boolean
Example:
if (balancy.itemHasDecayEffect(item)) {
// Show timer icon
timerIcon.style.display = '';
}
Prefab & Element Management¶
balancy.instantiatePrefab(prefabId)¶
Loads and instantiates a prefab by ID.
Parameters:
prefabId(string): The prefab identifier
Returns: Promise<HTMLElement>
Example:
const element = await balancy.instantiatePrefab('3871');
document.body.appendChild(element);
balancy.instantiatePrefabById(prefabId)¶
Loads, instantiates, and returns an ElementObject for a prefab.
Parameters:
prefabId(string): The prefab identifier
Returns: Promise<ElementObject>
Example:
const cardObject = await balancy.instantiatePrefabById('item-card');
const buyButton = cardObject.getComponent(Balancy_UI_Common_BuyButton);
buyButton.init({ price: myPrice });
document.body.appendChild(cardObject.element);
Global Variables¶
Constants & Enums¶
RequestAction¶
balancy.RequestAction = {
None: 0,
GetProfile: 1,
SetProfile: 2,
GetDocument: 3,
GetLocalization: 10,
GetImageUrl: 11,
GetInfo: 12,
CanBuyGroupOffer: 13,
GetBattlePassProgress: 20,
GetCustomEventInfo: 21,
SetCustomEventInfo: 22,
GetTasksInfoForTheEvent: 23,
ActivateTasksForTheEvent: 24,
DeactivateTasksForTheEvent: 25,
ClaimTaskReward: 26,
GetCustomDocumentInfo: 27,
SetCustomDocumentInfo: 28,
StopEventManually: 29,
GetInventoryItemsCount: 30,
AddInventoryItems: 31,
RemoveInventoryItems: 32,
WatchRewardedAd: 40,
RestoreFailedTask: 41,
BuyOffer: 101,
BuyGroupOffer: 102,
BuyShopSlot: 103,
BattlePassClaim: 104,
CloseWindow: 200,
BalancyIsReady: 201,
SetEmergencyExitEnabled: 203,
CustomMessage: 1000
};
InfoType¶
balancy.InfoType = {
None: 0,
OfferPrice: 1,
OfferGroupPrice: 2,
TimeLeft: 3,
OwnerLocalizedKey: 4,
OwnerCustom: 5,
CustomPrice: 9,
Custom: 10
};
BattlePassStatus¶
balancy.BattlePassStatus = {
NotAvailable: 0,
Available: 1,
Claimed: 2
};
TaskStatus¶
balancy.TaskStatus = {
Active: 0,
Completed: 1,
Failed: 2,
Claimed: 3
};
PriceType¶
balancy.PriceType = {
Hard: 1, // Real money (IAP)
Soft: 2, // Virtual currency
Ads: 3 // Rewarded ads
};
BuyButtonState¶
balancy.BuyButtonState = {
Available: 0, // Ready to purchase
Unavailable: 1, // Disabled
Cooldown: 2, // On cooldown with timer
Locked: 3 // Locked with overlay
};
Best Practices¶
1. Handle Async Operations¶
// ✓ Good: Use async/await
async function loadData() {
const level = await balancy.getSystemProfileValue('GeneralInfo.Level');
const coins = await balancy.getProfileValue('Profile', 'Currency.Coins');
updateUI(level, coins);
}
// ✗ Avoid: Not handling promises
function loadData() {
const level = balancy.getSystemProfileValue('GeneralInfo.Level'); // This is a Promise!
console.log(level); // Logs: Promise { <pending> }
}
2. Check for Null/Undefined¶
// ✓ Good: Check before accessing
const offers = await balancy.getActiveOffers();
if (offers && offers.length > 0) {
displayOffer(offers[0]);
}
// ✗ Avoid: Assuming data exists
const offers = await balancy.getActiveOffers();
displayOffer(offers[0]); // May throw if offers is empty
3. Use Error Handling¶
// ✓ Good: Handle errors
try {
const result = await balancy.buyOffer(offerInfo.instanceId);
showSuccess(result);
} catch (error) {
console.error('Purchase failed:', error);
showError(error.message);
}
// ✗ Avoid: No error handling
const result = await balancy.buyOffer(offerInfo.instanceId);
showSuccess(result); // What if it fails?
4. Clean Up Listeners¶
// ✓ Good: Unsubscribe when done
const unsubscribe = balancy.subscribeToCustomMessages(handler);
// Later...
unsubscribe();
// ✗ Avoid: Memory leaks
balancy.subscribeToCustomMessages(handler);
// Never unsubscribed - handler keeps running
Next Steps¶
- Learn Data Attributes for declarative UI
- Check Events System for lifecycle events
- See Built-in Scripts for examples of API usage
balancy.stopEventManually(cooldown, instanceId)¶
Stops the event selected by its runtime EventInfo instance ID. Pass -1 for the configured cooldown, 0 for no cooldown, or a cooldown override in seconds. Configuration unnyId is not accepted in the explicit context argument.
await balancy.stopEventManually(-1, eventInfo.instanceId);
Event removal lifecycle¶
balancy.stopEventManually(-1, eventInfo.instanceId) stops an active event or removes a retained Finished event. Finished removal emits only balancy.NotificationType.OnEventRemoved (113), never a second Deactivated. Listen to balancy-notification and use event.detail.instance_id for removal. Complete final writes/reward claims before stopping. See event completion and removal for the scenario table and host SDK examples.