Xtopay Docs
Credit Wallets

Issuing Wallets

Create wallets for your customers and manage their balances.

Create a wallet

Each customer can hold one wallet per currency. Create it at account registration or on first use.

const wallet = await xtopay.wallets.create({
  customer_id: "cus_abc123",
  currency: "GHS",
  metadata: {
    tier: "pro",
  },
});

If the customer already has a wallet in that currency, the API returns the existing one — creation is idempotent on (customer_id, currency).

Retrieve a wallet

const wallet = await xtopay.wallets.retrieve("wal_a1b2c3");

// Or by customer and currency
const wallet = await xtopay.wallets.retrieveByCustomer({
  customer_id: "cus_abc123",
  currency: "GHS",
});

Check balance

const wallet = await xtopay.wallets.retrieve("wal_a1b2c3");
console.log(wallet.balance);           // e.g. 15000 (GHS 150.00)
console.log(wallet.balance_formatted); // "GH₵150.00"

Always check wallet.balance server-side before allowing a debit — never trust a client-sent balance.

Wallet statuses

StatusMeaning
activeNormal — top-ups and debits allowed
frozenDebits blocked — top-ups still accepted
closedNo activity allowed — remaining balance must be refunded

Freeze or close a wallet from the dashboard or API:

await xtopay.wallets.freeze("wal_a1b2c3");
await xtopay.wallets.unfreeze("wal_a1b2c3");
await xtopay.wallets.close("wal_a1b2c3");

Credit adjustment (admin credit)

Grant credit without a top-up payment — for promotions, goodwill credits, or referral bonuses:

await xtopay.wallets.credit({
  wallet_id: "wal_a1b2c3",
  amount: 1000,          // GHS 10.00 — free credit
  description: "Welcome bonus",
  reference: "promo_welcome_2026",
});

Admin credits do not generate a payment or charge the customer.

Balance expiry

Configure credits to expire after a set period — useful for promotional credits that shouldn't accumulate indefinitely:

await xtopay.wallets.credit({
  wallet_id: "wal_a1b2c3",
  amount: 500,
  description: "Monthly bonus credits",
  expires_at: "2026-08-01T00:00:00Z",
});

Expired credits are removed automatically and a wallet.credit_expired webhook fires.

On this page