-
Notifications
You must be signed in to change notification settings - Fork 0
Developer API
This page describes UBS API access for other mods/plugins and the built-in placeholder resolver.
API baseline in this release: 1.3.0
Dashboard addon API baseline: 2.0.0
Need implementation guidance? Start with the Developer Integration Tutorial. For web dashboard extensions, see Dashboard Addon API.
Use:
UltimateBankingApi api = UltimateBankingApiProvider.get();Dashboard host API:
UltimateBankingDashboardApi dashboardApi = UltimateBankingDashboardApiProvider.get();Dashboard pages are component-driven in 2.0.0: use DashboardPageDefinition, DashboardComponentDefinition, and DashboardComponents builders to define reusable UBS-styled pages without custom HTML/CSS. The full reference for widget/component types, left-nav panels, layout defaults, form actions, and addon data routes is Dashboard Addon API.
Banking actions:
getBalance(accountId)deposit(accountId, amount)deposit(accountId, amount, reference)withdraw(accountId, amount)withdraw(accountId, amount, reference)transfer(senderAccountId, receiverAccountId, amount)transfer(senderAccountId, receiverAccountId, amount, reference)depositToPrimary(playerId, amount, reference)withdrawFromPrimary(playerId, amount, reference)transferFromPrimary(senderPlayerId, receiverAccountId, amount, reference)transferToPrimary(senderAccountId, receiverPlayerId, amount, reference)shopPurchase(accountId, amount, shopName)shopPurchase(payerAccountId, merchantAccountId, amount, shopName, reference)issueBankNote(sourceAccountId, amountDollars, issuerPlayerId, issuerName)issueCheque(sourceAccountId, recipientPlayerId, amountDollars, writerPlayerId, writerName, recipientName)giveDollarBills(playerId, denomination, billCount)takeDollarBills(playerId, denomination, billCount)giveCoins(playerId, denominationCents, coinCount)takeCoins(playerId, denominationCents, coinCount)
amount can be a long for whole-dollar style integrations. Reference-aware deposit, withdraw, transfer, and primary-account helpers also accept BigDecimal for precise prices such as auction bids with cents.
Service/runtime checks:
getApiVersion()isServerAvailable()getPrimaryAccountId(playerId)accountExists(accountId)bankExists(bankId)getAccountStatus(accountId)validateAccountCanSend(accountId, amount)validateAccountCanReceive(accountId)sendUiAlert(playerId, title, message, tone, durationMs)sendUiAlert(playerId, title, message, success, durationMs, toneCode)sendLegacyUiAlert(playerId, title, legacyMessage, durationMs)sendSuccessUiAlert(playerId, title, message, durationMs)sendErrorUiAlert(playerId, title, message, durationMs)sendInfoUiAlert(playerId, title, message, durationMs)sendWarningUiAlert(playerId, title, message, durationMs)getSupportedUiAlertTones()sendNotification(playerId, request)dismissNotification(playerId, notificationId)clearNotificationChannel(playerId, channel)clearNotifications(playerId)getSupportedNotificationTypes()getSupportedNotificationPriorities()getSupportedNotificationPlacements()playerHasAnyAccount(playerId)playerHasPrimaryAccount(playerId)playerHasAvailableAccount(playerId)playerHasAvailablePrimaryAccount(playerId)playerHasFrozenAccount(playerId)playerOwnsAccount(playerId, accountId)playerOwnsBank(playerId, bankId)accountBelongsToBank(accountId, bankId)accountIsFrozen(accountId)accountIsPrimary(accountId)accountCanSend(accountId, amount)accountCanReceive(accountId)primaryAccountCanSend(playerId, amount)primaryAccountCanReceive(playerId)bankAcceptsTransactions(bankId)
Formatting helpers:
-
formatMoneyRounded(amount)-> configured-currency display string
formatMoneyRounded accepts BigDecimal or long amounts and returns a compact display string using the configured UBS currency symbol. It rounds to two decimals and carries rounded suffixes to the next scale, so 999999 can display as $1M. Use this for user-facing integration UIs such as auction-house cards, shop screens, and alerts. Keep using raw BigDecimal values for storage, sorting, validation, and transactions.
shopPurchase overload note:
-
shopPurchase(accountId, amount, shopName)is a simple label-based purchase. -
shopPurchase(payerAccountId, merchantAccountId, amount, shopName, reference)is the terminal-grade path (explicit merchant routing + external reference string).
Reference-aware transaction methods:
- The overloads with
referencereturnApiTransactionResultinstead ofApiResult. -
referenceis stored in the transaction description after a stable operation prefix, making external systems such as auction houses, shops, jobs, and quest rewards auditable in UBS transaction history. -
depositToPrimary,withdrawFromPrimary,transferFromPrimary, andtransferToPrimaryare convenience helpers for integrations that only know a player UUID. - These helpers still validate frozen accounts, bank status, account ownership, balance, and transaction limits server-side.
- For auction-house settlement, prefer
transferFromPrimary(winningBidderId, sellerAccountId, bidAmount, "YOURMOD_AUCTION:<auction-id>")over minting money withdepositToPrimary.
ApiTransactionResult fields:
successreasontransactionIdsenderAccountIdreceiverAccountIdamountbalanceAfterdescription
These methods expose stable read models for integration UIs, HUDs, dashboards, and leaderboards.
-
getAccountSnapshot(accountId)->Optional<ApiAccountSnapshot> -
getPrimaryAccountSnapshot(playerId)->Optional<ApiAccountSnapshot> -
getPlayerAccounts(playerId)->List<ApiAccountSnapshot> -
getPlayerAccountIds(playerId)->List<UUID> -
getBankAccounts(bankId)->List<ApiAccountSnapshot> -
setPrimaryAccount(playerId, accountId)->ApiResult -
getPrimaryAccountId(playerId)andgetPrimaryAccountSnapshot(playerId)return empty when no owned account is explicitly marked primary.
ApiAccountSnapshot fields:
accountIdplayerIdbankIdaccountTypeaccountTypeLabelbalanceprimaryfrozenfrozenReasoncreatedAt
Use these helpers when an integration only needs a yes/no answer and should not duplicate UBS account-status rules.
-
getPlayerAccountIds(playerId)returns the player's account UUIDs, sorted the same way asgetPlayerAccounts: primary accounts first, then newest accounts. -
playerHasAnyAccount(playerId)returnstruewhen UBS has at least one account registered to that player UUID. -
playerHasPrimaryAccount(playerId)returnstruewhen the player has a primary account selected. -
playerHasAvailableAccount(playerId)returnstruewhen at least one owned account can currently receive normal banking activity. -
playerHasAvailablePrimaryAccount(playerId)returnstruewhen the player's primary account exists and has statusAVAILABLE. -
playerHasFrozenAccount(playerId)returnstruewhen any owned account is frozen. -
playerOwnsAccount(playerId, accountId)checks account ownership. -
playerOwnsBank(playerId, bankId)checks bank ownership. -
accountBelongsToBank(accountId, bankId)checks account-to-bank membership. -
accountIsFrozen(accountId)checks whether an account is frozen. -
accountIsPrimary(accountId)checks whether an account is marked as the owner's primary account. -
accountCanSend(accountId, amount)returnstrueonly ifvalidateAccountCanSendwould succeed. -
accountCanReceive(accountId)returnstrueonly ifvalidateAccountCanReceivewould succeed. -
primaryAccountCanSend(playerId, amount)checks the player's primary account and returnsfalseif no primary account exists. -
primaryAccountCanReceive(playerId)checks whether the player's primary account can receive funds. -
bankAcceptsTransactions(bankId)returnsfalseif the bank is missing or in a transaction-blocking state such asSUSPENDED,REVOKED, orLOCKDOWN.
amount accepts long or BigDecimal for accountCanSend and primaryAccountCanSend.
API 1.3.0 adds a stackable, scenario-aware notification system for integrations. It supports stable IDs, in-place progress updates, duplicate collapsing, priorities, sticky notices, adaptive placement, and server-controlled dismissal. UBS uses this path internally.
Methods:
-
sendNotification(playerId, request)->ApiNotificationResult -
dismissNotification(playerId, notificationId)->ApiNotificationResult -
clearNotificationChannel(playerId, channel)->ApiNotificationResult -
clearNotifications(playerId)->ApiNotificationResult -
getSupportedNotificationTypes()->List<ApiNotificationType> -
getSupportedNotificationPriorities()->List<ApiNotificationPriority> -
getSupportedNotificationPlacements()->List<ApiNotificationPlacement>
Build requests with ApiNotificationRequest.builder(type, message) or a convenience factory:
success(message)error(message)warning(message)info(message)transaction(message)security(message)progress(id, message)
Request fields:
-
id: stable identifier used for update/dismiss; an empty ID is generated by UBS. -
channel: logical group used byclearNotificationChannel; defaults togeneral. -
source: short integration/product label shown in notification metadata. -
title,message,detail: primary and secondary copy.messageis required. -
type: visual scenario and icon. -
priority: stack order and emphasis. -
placement: preferred location, orAUTOfor context-aware placement. -
durationMs: visible duration, clamped to1500..30000ms. -
progress:0.0..1.0,NO_PROGRESS, orINDETERMINATE_PROGRESS. -
sticky: keeps the notice visible until explicitly dismissed or cleared. -
playSound: enables the priority/type-aware UI sound. -
replaceExisting: updates an existing matching ID in place; enabled by default.
ApiNotificationType values:
-
SUCCESS,ERROR,WARNING,INFO -
TRANSACTIONfor money/account/payment state -
SECURITYfor access, fraud, alarm, and authorization state -
MESSAGEfor communication events -
PROGRESSfor work that updates in place -
SYSTEMfor general system state
ApiNotificationPriority values are LOW, NORMAL, HIGH, and CRITICAL. Priority is independent from type: a transaction can be normal while a security breach can be critical.
ApiNotificationPlacement values:
-
AUTO: top-right during gameplay, bottom-right above open screens, and top-center for critical/small-screen notices. TOP_RIGHTTOP_CENTERBOTTOM_RIGHT
Example:
ApiNotificationRequest request = ApiNotificationRequest.transaction("$250 was transferred.")
.id("auction:settlement:" + auctionId)
.channel("auction_house")
.source("Ultimate Auction System")
.title("Settlement complete")
.detail("The seller account has been credited.")
.priority(ApiNotificationPriority.NORMAL)
.durationMs(5500)
.build();
ApiNotificationResult result = api.sendNotification(playerId, request);Progress update example:
String id = "auction:sync:" + playerId;
api.sendNotification(playerId, ApiNotificationRequest.progress(id, "Syncing listings")
.source("Ultimate Auction System")
.progress(0.25F)
.build());
// Reusing the ID updates the visible card instead of adding another card.
api.sendNotification(playerId, ApiNotificationRequest.progress(id, "Syncing listings")
.source("Ultimate Auction System")
.progress(0.80F)
.build());
api.dismissNotification(playerId, id);Behavior and limits:
- The target must be online. Offline sends return
success=falseand do not queue for later delivery. - Rapid identical notices collapse into one card with a repeat counter.
- Up to four cards render in each placement stack; excess state is bounded client-side.
- Critical notifications receive stronger visual emphasis but do not pause gameplay.
- Text is bounded in transport: ID 72, channel 48, source 64, title 96, message 512, and detail 256 characters.
- Notifications render above open UBS screens and use responsive widths/wrapping on small GUI scales.
- Use a stable ID for progress or state changes. Use generated IDs for independent events.
- Use channels to clear a related workflow without removing unrelated notices.
ApiNotificationResult reports success, reason, playerId, notificationId, and channel.
The original top-center action-card API remains available and unchanged for binary/source compatibility with older integrations. New integrations should use Notification API v2. Legacy calls deliberately continue to use the old renderer rather than silently changing their appearance or queue behavior.
Methods:
-
sendUiAlert(playerId, title, message, tone, durationMs)->ApiAlertResult -
sendUiAlert(playerId, title, message, success, durationMs, toneCode)->ApiAlertResult -
sendLegacyUiAlert(playerId, title, legacyMessage, durationMs)->ApiAlertResult -
sendSuccessUiAlert(playerId, title, message, durationMs)->ApiAlertResult -
sendErrorUiAlert(playerId, title, message, durationMs)->ApiAlertResult -
sendInfoUiAlert(playerId, title, message, durationMs)->ApiAlertResult -
sendWarningUiAlert(playerId, title, message, durationMs)->ApiAlertResult -
getSupportedUiAlertTones()->List<ApiAlertTone>
ApiAlertTone values:
-
SUCCESS(toneCode0) -
ERROR(toneCode1) -
INFO(toneCode2) -
WARNING(toneCode3)
ApiAlertResult fields:
successreasonplayerIdtitlemessagealertSuccessdurationMstonetoneCode
Behavior:
- The target player must be online; offline players return
success=falsewith reasonPlayer is not online. -
messageis required and blank messages are rejected. -
durationMsis clamped by the UBS alert payload to the supported display window. -
sendLegacyUiAlertstrips legacy formatting codes and infers tone from color/error wording. - The raw overload with
successandtoneCodeexists for integrations that need every payload parameter. Prefer theApiAlertToneoverload for normal use.
-
getBankSnapshot(bankId)->Optional<ApiBankSnapshot> -
getBanks()->List<ApiBankSnapshot>
ApiBankSnapshot fields:
bankIdbankNameownerIdstatusdeclaredReservetotalDepositsminimumRequiredReservereserveRatiooutstandingLoanBalancemaxLendableAmountinterestRateaccountCount
-
getTransactionSnapshot(transactionId)->Optional<ApiTransactionSnapshot> -
getAccountTransactions(accountId, limit)->List<ApiTransactionSnapshot> -
getPlayerTransactions(playerId, limit)->List<ApiTransactionSnapshot>
ApiTransactionSnapshot fields:
transactionIdsenderAccountIdreceiverAccountIdamounttimestampdescription
These methods let integrations issue real UBS instruments and physical USD legal tender cash items.
-
issueBankNote(sourceAccountId, amountDollars, issuerPlayerId, issuerName)->ApiItemResult -
issueCheque(sourceAccountId, recipientPlayerId, amountDollars, writerPlayerId, writerName, recipientName)->ApiItemResult
Behavior:
- Withdraws the amount from
sourceAccountId. - Returns a fully tagged
ItemStack(bank_noteorcheque) ready to give/store. - Returns the generated serial/ID in
referenceId.
ApiItemResult fields:
successreasonitemStackreferenceIdamount
-
giveDollarBills(playerId, denomination, billCount)->ApiCashResult -
takeDollarBills(playerId, denomination, billCount)->ApiCashResult -
getSupportedBillDenominations()->List<Integer> -
createDollarBillStacks(denomination, billCount)->List<ItemStack> -
getPlayerBillCount(playerId, denomination)->int -
getPlayerCashOnHand(playerId)->int -
getPlayerCashOnHandCents(playerId)->int
denomination values are face-value dollars: 1, 2, 5, 10, 20, 50, 100.
billCount means count of bill items, not dollar amount.
-
giveCoins(playerId, denominationCents, coinCount)->ApiCashResult -
takeCoins(playerId, denominationCents, coinCount)->ApiCashResult -
getSupportedCoinDenominations()->List<Integer> -
createCoinStacks(denominationCents, coinCount)->List<ItemStack> -
getPlayerCoinCount(playerId, denominationCents)->int -
getPlayerCashOnHand(playerId)->int(bills + coins) -
getPlayerCashOnHandCents(playerId)->int(bills + coins in cents)
denominationCents values: 1, 5, 10, 25, 50.
coinCount means count of coin items, not cent total.
getPlayerCashOnHand(playerId) returns whole dollars and truncates leftover cents. Use getPlayerCashOnHandCents(playerId) when exact coin-aware value is needed.
ApiCashResult fields:
successreasondenominationbillCounttotalDollarValue
For coin operations, denomination and totalDollarValue use the provided cent-denomination value. Treat totalDollarValue as a legacy integer total for the returned denomination/count pair, not as a precise cross-denomination wallet value.
UBS now also exposes aggregate values for leaderboards and HUD overlays:
getPlayerTotalBalance(playerId)getPlayerPrimaryBalance(playerId)getPlayerAccountCount(playerId)getBankTotalDeposits(bankId)getBankReserve(bankId)getBankStatus(bankId)
UBS now exposes read methods for pickpocket history checks:
-
hasPlayerEverStolen(playerId)->boolean -
getPlayersStolenFrom(playerId)->List<UUID>
These methods are intended for moderation dashboards, custom HUD stats, and server-side progression hooks.
Use this when you want token-based text expansion:
resolvePlaceholder(playerId, token)resolvePlaceholders(playerId, text)getSupportedPlaceholders()
If a token is unknown, resolvePlaceholder returns empty string.
resolvePlaceholders leaves unknown %token% values unchanged.
Player scope:
%ubs_player_total_balance%%ubs_player_total_balance_raw%%ubs_player_primary_balance%%ubs_player_primary_balance_raw%%ubs_player_account_count%%ubs_player_primary_account_id%%ubs_player_primary_account_type%%ubs_player_primary_bank_id%%ubs_player_primary_bank_name%
Primary-bank scope (uses player's primary bank):
%ubs_bank_name%%ubs_bank_id%%ubs_bank_status%%ubs_bank_reserve%%ubs_bank_reserve_raw%%ubs_bank_total_deposits%%ubs_bank_total_deposits_raw%
Explicit bank-id scope:
%ubs_bank_name_<bank-uuid>%%ubs_bank_status_<bank-uuid>%%ubs_bank_reserve_<bank-uuid>%%ubs_bank_reserve_raw_<bank-uuid>%%ubs_bank_total_deposits_<bank-uuid>%%ubs_bank_total_deposits_raw_<bank-uuid>%
- Non-raw money placeholders return abbreviated display values (example:
$1.2M). -
formatMoneyRounded(amount)returns rounded abbreviated display values (example:$1.23K) for integration UI text. -
_rawplaceholders return plain numeric decimal strings (example:1234567.89) suitable for sorting/ranking systems.
UltimateBankingApi api = UltimateBankingApiProvider.get();
String label = api.formatMoneyRounded(new BigDecimal("1234.56")); // "$1.23K" by defaultUUID playerId = player.getUUID();
UltimateBankingApi api = UltimateBankingApiProvider.get();
String line = api.resolvePlaceholders(
playerId,
"Net Worth: %ubs_player_total_balance% | Accounts: %ubs_player_account_count%"
);String raw = api.resolvePlaceholder(playerId, "%ubs_player_total_balance_raw%");
BigDecimal value = new BigDecimal(raw);UltimateBankingApi api = UltimateBankingApiProvider.get();
api.getPrimaryAccountSnapshot(player.getUUID()).ifPresent(primary -> {
System.out.println("Primary account: " + primary.accountId());
System.out.println("Balance: " + primary.balance());
});
for (ApiBankSnapshot bank : api.getBanks()) {
System.out.println(bank.bankName() + " reserve ratio = " + bank.reserveRatio());
}UltimateBankingApi api = UltimateBankingApiProvider.get();
ApiCashResult result = api.giveDollarBills(player.getUUID(), 20, 6); // six $20 bills
if (!result.success()) {
System.out.println("Failed to give bills: " + result.reason());
}UltimateBankingApi api = UltimateBankingApiProvider.get();
ApiCashResult result = api.giveCoins(player.getUUID(), 25, 12); // twelve quarters
if (!result.success()) {
System.out.println("Failed to give coins: " + result.reason());
}UltimateBankingApi api = UltimateBankingApiProvider.get();
ApiItemResult cheque = api.issueCheque(
sourceAccountId,
recipientPlayerId,
250L,
writerPlayerId,
"Bank Admin",
"RecipientName"
);
if (cheque.success()) {
ItemStack stack = cheque.itemStack();
// give to player inventory or store for later
}