@faiber/faiber-asset
Wallets, balances, plans, subscriptions, purchases, ranks, rewards, usage, bank transactions, sandbox billing, and service lifecycle operations.
Install
npm install @faiber/faiber-asset
Configure
import { FaiberClient, MemoryTokenProvider } from "@faiber/sdk-core";
import { AssetApi } from "@faiber/faiber-asset";
const tokens = new MemoryTokenProvider();
const client = new FaiberClient("asset", {
domains: { asset: process.env.FAIBER_ASSET_URL! },
tokenProvider: tokens,
axios: { timeout: 15_000, withCredentials: true },
});
const api = new AssetApi(client);
const assets = await api.assets.list({ "page[number]": 1 });
const wallet = await api.operations.walletBillingWalletShowGet();
Complete capability
This package exposes 110 registered operations from the assets and billing service. Common workflows have concise methods on api; every registered backend route is also available as a named function on api.operations. Generated operation input, query, response, path, verb, and permission contracts are exported from operations.types.
| Area | Operations | HTTP methods |
|---|---|---|
action | 6 | DELETE, GET, PATCH, POST |
ai-billing | 3 | POST |
bank | 5 | GET, PATCH, POST |
catalog | 5 | DELETE, GET, PATCH, POST |
charge | 2 | GET, PATCH |
dashboard | 1 | GET |
economy | 13 | GET, POST, PUT |
fitness | 1 | PUT |
game-escrow | 4 | GET, POST |
integration | 3 | GET |
leaderboard | 1 | GET |
llm-usage | 4 | DELETE, GET, PUT |
logs | 2 | GET |
rank | 5 | DELETE, GET, PATCH, POST |
router | 3 | GET |
sandbox-billing | 11 | DELETE, GET, POST, PUT |
service-lifecycle | 4 | DELETE, POST |
trial-gifts | 6 | GET, POST, PUT |
wallet | 9 | GET |
wallet-billing | 22 | DELETE, GET, POST, PUT |
Administrative and self-service billing routes are distinct operations. Purchase, top-up, pause, resume, removal, and permanent-data deletion methods preserve the backend verbs and permission annotations.
Scoped funded rewards
myEconomy(), economyValuation(), myEconomyHistory() and
economyLeaderboard({role, period_id}) expose classroom balances, funding capacity,
recovery blocks, session Charge, entitlements and separate role rankings. Monetary
amounts and Coin quantities are exact decimal strings. Valuation includes its
currency; divide IRR by 10 explicitly when displaying Toman.
const valuation = await api.economyValuation();
const preview = await api.previewEconomyReward({
action_name: "configured-action", role: "student", scope_id: classroomId,
source_id: verifiedEvidenceId, session_id: roomId, replay: false,
});
const purchase = await api.purchaseEconomyItem({
event_id: crypto.randomUUID(), item_id: "configured-pack", payment: "money",
});
Preview never changes a balance. Completion requires verified domain evidence or
an authorized operator using economyCommand() with an audit reason. Services
send funding, admission and interaction commands through RabbitMQ. Client HTTP
cannot fabricate those commands. Operator policy and journal methods require the
permissions documented on each method.
Reuse purchase/credit event_id when retrying. Money quotes lock the displayed
amount until expires_at; read the purchase from myEconomy() for its payment
redirect URL or provider error. Successful payment credits once. Coin redemption
can fail while refund recovery or a backing shortfall remains. Purchased credit
persists independently of session Charge; applySessionChargeCredit() fills only
space below the session maximum. All methods retain normal Axios error responses,
authorization and cancellation options.
Authentication and authorization
Configure the Asset URL to use your authenticated Faiber gateway. Use a TokenProvider for an in-memory Bearer token, or withCredentials for secure HttpOnly cookie sessions. The pinned Asset service reads trusted gateway identity headers; its route permission annotations describe gateway ACL metadata and do not themselves validate user Bearer tokens or cookies. An enforcing gateway must authenticate the caller and apply those permissions. Every SDK operation uses the shared FaiberClient transport.
Game escrow operations additionally require a server-only x-game-service-token header; fitness product publication uses its own server-only service Bearer token. These credentials must remain on a trusted server. Pass them through request options configured for the relevant operation.
Inputs, queries, responses, and transport
All methods return the complete Axios response, including status, headers, and request IDs. Decimal outputs such as wallet balances, catalog quantities and daily usage costs are strings; decimal inputs accept strings or numbers. Asset/rank/action deletes return data: null. Self-service subscriptions return data.subscriptions without pagination. Request bodies and query objects are named exported interfaces. Nested pagination uses keys such as page[number] and page[size] where required by the service. Standard Axios request options, headers, timeouts, adapters, interceptors, and AbortSignal cancellation are supported as the final argument.
Generic REST resources are capability-guarded. Calling a legacy method that the service does not register throws UnsupportedOperationError before sending a request instead of producing a backend 405.
Errors and cancellation
try {
await api.client.get("/health", undefined, { signal: AbortSignal.timeout(5_000) });
} catch (error) {
// Axios errors retain response.status and the service error body.
}
Use @faiber/faiber-ts-sdk when one application needs multiple Faiber services with one configuration.
Trial gifts and wallet checkout
operations.trialGiftsListGet(product, query) pages through product-owned gifts; trialGiftsCreatePost, trialGiftsUpdatePut, and trialGiftsCopyTokenGet administer them. Product IDs are 2done and fitapp. Both the declared admin Charge permission and the Asset Charge permission are required. Reuse request_id when creating a gift; token copying requires an available vault and an unused gift.
operations.sandboxBillingQuoteResourcesPost(input) quotes resources without allocating or debiting. Monetary quote values are decimal strings. walletBillingWalletSubscriptionsPost atomically purchases subscriptions from the current wallet with a stable request_id and a maximum accepted amount; changed quotes return 409 and insufficient balance returns 402. walletBillingWalletPurchaseShowGet reads only the authenticated owner's receipt. Fitness product publication is server-only and rejects changes to an already published tier.
Catalog and rule models
Create assets with {name, asset_type} (Coin, Badge, XP, Charge, or Gem) and ranks with {name, min_xp}. User AI plan updates accept {tier}. dashboard({month: "2026-10"}) selects a month. Charge mapping conditions are tagged objects such as {type: "xp_balance", operator: "gte", value: "100"}. Action criteria, reward conditions, caps and multiplier models are exported alongside the operation models.
economyPolicy() returns null before configuration and includes configuration_revision afterward; policy updates return the saved policy. Policy models include funding settings and evidence bindings, and capabilities include rule creation/update flags. Economy journal accepts before and descending; own-history supports after and limit only. Gift list/detail payloads remain product-owned JSON because Asset forwards the configured adapter's data unchanged; Asset annotates detail/items with can_copy and exposes a concrete token-copy response.
Funded Do and private Dox
asset.doEconomy manages the separately configured funded-rewards policy. It does
not change the existing scoped economy's prohibition on coin purchases. Prices
use integer rial and integer coins. Operators configure inactive packs, catalog
items, backing, delivery costs, review requirements and promotion reserves.
Policy updates require admin:coin_settings:update, a current version and an
audit reason. Read-only policy/audit calls require admin:coin_settings:read.
Campaign funding uses a stable request_id; retries cannot issue twice.
Financial transfers, purchases and entitlement delivery require trusted backend
integrations. Never put their credentials in a browser.
const snapshot = await asset.doEconomy.policy({ signal: controller.signal });
console.log(snapshot.data.data.version, snapshot.data.data.policy.enabled);
Generic Dox ledger (trusted backends)
Dox is a closed, space-scoped asset independent of purchasable Do. AssetApi.dox
owns issuance, account balances, immutable postings, replay protection, and
atomic transfers. Task checks membership and work-review permissions before
requesting a transfer. No browser application holds the service credential.
const asset = new AssetApi(new FaiberClient('asset', {
domains: { asset: process.env.ASSET_URL! }, authMode: 'cookie'
}));
const result = await asset.dox.management({
profile_id: moderatorId, space_id: spaceId,
dox_management: { account: 'space', direction: 'out', page: 1, page_size: 20 }
}, { headers: { 'x-do-service-token': process.env.ASSET_TASK_TOKEN! }, signal });
execute() accepts named configure/transfer commands with a stable id and
actor_id. The source/destination UUID is a member; null represents the space.
Each member receives a one-time 500 allocation, routed by the configured mode.
Transfers conserve supply and reject overspending. A task or purchase identity
cannot pay twice even with a different request ID. management() is Task-service
only; read() pages one member's history. Page size is 1–100; direction requires
an account (space or user:UUID). Full Axios responses and cancellation are
preserved; handle 401/403, insufficient balance, and conflicting replays. These
contracts are generic and contain no product routing or UI assumptions.
Administering a product’s Do policy
Use DoEconomyApi with your existing authenticated FaiberClient('asset', …).
policy() returns { version, can_edit, policy } inside response.data.data.
savePolicy({ version, policy, reason }) updates that same version, records an
audit reason, and returns the saved snapshot. Read and write require
admin:coin_settings:read and admin:coin_settings:update, respectively.
Never put trusted backend service tokens in an admin browser.
The policy includes packs, products, bilingual gifts, personalization rewards, the daily payout sequence, referral rewards and limits, campaign funding and resubmission limits, and funding/review rules. Gift image paths must be local, identifiers unique, and amounts valid integers. Existing policies default to zero personalization rewards and an empty check-in schedule. An empty schedule disables daily coin grants; otherwise days beyond it use the final amount.
Read the saved policy before editing and preserve fields outside your form.
On do.version_conflict, retain the draft and explicitly reload/reconcile the
new revision; do not retry with a guessed version. Backend validation rejects
underfunded packs and invalid values. Both calls preserve full Axios responses
and accept RequestOptions, including an abort signal.