Billing & wallet

@hyperyai/sdk wallet hooks — useWallet for the AI-credit wallet (balance, 1-click add funds, add a payment method) and useBuyerWallet for marketplace buyer cards.

The SDK has two wallets, matching Hypery's two payment flows:

  • useWallet — the signed-in user's AI-credit wallet: the balance AI requests are billed against, plus funding actions.
  • useBuyerWallet — the buyer's saved cards for marketplace purchases and subscriptions (Stripe Connect).

To turn a billing error into UI automatically, see Error handling. For purchases, subscriptions and top-ups with login and card entry handled, see Checkout & payments.

useWallet

Loads GET /api/wallet/state when the user is signed in.

import { useWallet } from '@hyperyai/sdk';
 
function Balance() {
  const { wallet, isLoading, error, addFunds, addPaymentMethod } = useWallet({
    gatewayUrl: 'https://hypery.ai',
  });
  if (isLoading || !wallet) return null;
 
  if (!wallet.paymentMethod.exists) {
    return <button onClick={() => addPaymentMethod()}>Add a card</button>;
  }
  return (
    <div>
      <p>{wallet.balance.current} credits · {wallet.paymentMethod.brand} •••• {wallet.paymentMethod.last4}</p>
      {wallet.mode === 'prepaid' && <button onClick={() => addFunds(10)}>Add $10</button>}
    </div>
  );
}
OptionTypeDefaultDescription
gatewayUrlstringprovider gatewayUrlBase URL override. Falls back to the provider's gatewayUrl, then NEXT_PUBLIC_GATEWAY_URL, then a relative path.
ReturnsTypeDescription
walletWalletState | nullWallet snapshot (below); null when signed out.
isLoadingbooleanLoading state.
errorstring | nullLoad error message.
reload() => Promise<void>Re-fetch.
addFunds(usd: number) => Promise<void>Charges the card on file for usd dollars (POST /api/wallet/topup) and reloads. Throws on failure.
addPaymentMethod() => Promise<boolean>Opens Stripe-hosted Checkout (setup mode) in a popup. Resolves true when the gateway's return page reports the card was added, false if the popup closes first. Reloads either way.

WalletState:

FieldTypeDescription
modeBillingModeBilling mode of the team. 'metered' | 'prepaid' | 'vag_passthrough'. In vag_passthrough usage is billed to the card directly and the balance fields are 0.
balance{ current, reserved, monthlySpent, monthlyLimit }Credits (100 credits = $1).
paymentMethod{ exists, last4?, brand? }Card on file.
autoTopUp{ enabled, threshold?, amount? }Auto top-up settings.
lowBalance{ isLow, threshold, current }Low-balance indicator.
topupTiersWalletTier[]{ name, usdAmount, credits, bonus, popular? }.
settingsUrls{ billing, topup, addPaymentMethod }Paths on the gateway for the hosted billing pages.

Credits are spend-only: they are added by purchase, auto top-up, bonus or refund, and are never earned from usage or cashed out. See Credits for how billing modes work.

useBuyerWallet

Loads the buyer's saved marketplace cards from GET /api/buyer/wallet (via authenticatedFetch, using the provider's gatewayUrl).

import { useBuyerWallet } from '@hyperyai/sdk';
 
function Cards() {
  const { paymentMethods, hasDefault, isLoading, addCard } = useBuyerWallet();
  if (isLoading) return null;
  return (
    <div>
      {paymentMethods.map((pm) => (
        <p key={pm.id}>{pm.brand} •••• {pm.last4} {pm.isDefault && '(default)'}</p>
      ))}
      {!hasDefault && <button onClick={() => addCard({ successUrl: location.href })}>Add a card</button>}
    </div>
  );
}
ReturnsTypeDescription
paymentMethodsBuyerPaymentMethod[]{ id, brand, last4, expMonth, expYear, isDefault }.
hasDefaultbooleanA default card is set.
isLoadingbooleanLoading state.
errorParsedError | nullClassified load error (e.g. isAuth when signed out).
refresh() => Promise<void>Re-fetch.
addCard(opts?: AddCardOptions) => Promise<void>Starts Stripe-hosted card entry (POST /api/buyer/wallet/checkout-setup) and redirects the page to it. Throws if the session can't be created.

AddCardOptions: successUrl? and cancelUrl? — where Stripe returns; both default to the current URL.

You rarely need addCard directly: useCheckout, BuyButton and SubscribeButton ask for a card only when the charge needs one.

Next steps