Balancy JavaScript API¶
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)¶
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);
document.getElementById('buy-button').disabled = !canBuy;
Purchases¶
balancy.buyOffer()¶
Purchases the current offer (uses window.balancyViewOwner context).
Returns: Promise<PurchaseResult>
Example:
try {
const result = await balancy.buyOffer();
console.log('Purchase successful:', result);
} catch (error) {
console.error('Purchase failed:', error);
}
balancy.buyGroupOffer(index)¶
Purchases a specific offer from a group.
Parameters:
index(number): Offer index within the group
Returns: Promise<PurchaseResult>
Example:
const result = await balancy.buyGroupOffer(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.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();
Battle Pass¶
balancy.getBattlePassConfig()¶
Gets the configuration for the current battle pass.
Returns: Promise<BattlePassConfig>
Example:
const config = await balancy.getBattlePassConfig();
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()¶
Gets the current player's battle pass progress.
Returns: Promise<BattlePassProgress>
Example:
const progress = await balancy.getBattlePassProgress();
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)¶
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);
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()¶
Gets the list of active tasks.
Returns: Promise<Task[]>
Example:
const tasks = await balancy.getTasks();
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();
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)¶
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']);
balancy.deactivateTasks(taskIds)¶
Deactivates tasks.
Parameters:
taskIds(string[]): Array of task IDs
Returns: Promise<void>
Example:
await balancy.deactivateTasks(['quest-1', 'quest-2']);
balancy.getCustomEventInfo()¶
Gets custom event data stored on the backend.
Returns: Promise<any>
Example:
const eventData = await balancy.getCustomEventInfo();
console.log('Event progress:', eventData.progress);
balancy.setCustomEventInfo(data)¶
Saves custom event data to the backend.
Parameters:
data(any): Data to save (will be JSON serialized)
Returns: Promise<void>
Example:
await balancy.setCustomEventInfo({
started: true,
progress: 50,
lastCheckpoint: 'level-3'
});
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.getTimeLeft()¶
Gets remaining time based on balancySettings.
Returns: number - Seconds remaining
Example:
const timeLeft = balancy.getTimeLeft();
document.getElementById('timer').textContent = balancy.formatTime(timeLeft);
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¶
window.balancyViewOwner¶
Contains context information about the current view.
Structure:
{
instanceId: "offer_123", // Current offer/event instance ID
unnyIdGameEvent: "663", // Game event ID (for battle pass, etc.)
unnyIdGameOffer: "1188", // Game offer ID
productId: "coin_pack_small", // Product ID for purchases
// ... other custom fields
}
Example:
const offerId = window.balancyViewOwner.unnyIdGameOffer;
const offerDoc = await balancy.getDocumentValue(offerId, 3);
window.balancySettings¶
Contains view settings and timing information.
Structure:
{
launchTime: 1751328000, // Unix timestamp when view was launched
secondsLeft: 86400 // Seconds remaining for time-limited content
}
Example:
const timeLeft = balancy.getTimeLeft(); // Uses balancySettings.secondsLeft
window.customFormatTime(seconds) 🗑️ OBSOLETE¶
⚠️ This override method is obsolete. Instead of using global function overrides, create custom script components that handle time formatting.
Override the default time formatting behavior.
Parameters:
seconds(number): Duration in seconds
Returns: string - Formatted time string
Example:
// ⚠️ Obsolete - use custom components instead
window.customFormatTime = function(seconds) {
if (seconds < 60) return `${seconds}s`;
if (seconds < 3600) return `${Math.floor(seconds/60)}m`;
return `${Math.floor(seconds/3600)}h`;
};
// ✓ Recommended: Create a custom component
class CustomTimer extends balancy.ElementBehaviour {
// @serialize {element}
timerText = null;
formatTime(seconds) {
if (seconds < 60) return `${seconds}s`;
if (seconds < 3600) return `${Math.floor(seconds/60)}m`;
return `${Math.floor(seconds/3600)}h`;
}
update(deltaTime) {
const timeLeft = balancy.getTimeLeft();
this.timerText.element.textContent = this.formatTime(timeLeft);
}
}
Why it's obsolete:
- Global function overrides make code harder to maintain
- Component-based approach is more reusable
- Better for team collaboration
- Easier to test and debug
Learn more: Prefabs & Components
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,
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();
showSuccess(result);
} catch (error) {
console.error('Purchase failed:', error);
showError(error.message);
}
// ✗ Avoid: No error handling
const result = await balancy.buyOffer();
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