Skip to content
In this section

Wallets

Query per-currency seller balances, ledger entries, and inter-wallet transfers using the Fynex GraphQL API.

A wallet is Fynex's per-currency balance ledger for a seller account. Each seller can hold multiple wallets — one per currency — and every settlement, payout, and split execution produces append-only ledger entries on the relevant wallet.

Note

Two ways to read wallets. This guide documents the GraphQL surface (POST /dashboard/graphql, cookie-session authenticated), which exposes the full ledger including individual WalletEntry rows and WalletTransfer records. There is also a seller-bearer-token REST surface for integrators who only need balances and transactions: - GET /payments-api/v1/wallets — list the seller's wallets with balance snapshots - POST /payments-api/v1/wallets — create a wallet in a currency - GET /payments-api/v1/wallets/{wallet_id} — a single wallet - GET /payments-api/v1/wallets/{wallet_id}/transactions — that wallet's transactions - POST /payments-api/v1/wallets/{wallet_id}/fund — fund it

The REST surface uses your Authorization: Bearer <seller_token> (no cookie), is seller-scoped, hides Fynex system wallets, and returns balances as availableBalanceMinor / heldBalanceMinor / pendingBalanceMinor / totalBalanceMinor, plus withdrawableBalanceMinor / maturingBalanceMinor for the payout maturity hold (minor units). See GraphQL Authentication for the cookie flow used by the GraphQL queries below.


Wallet types

The WalletType enum describes the role of each wallet:

Type Purpose
MAIN Primary seller balance — most payments settle here
SELLER_OPERATIONAL Operational float held by the seller
PAYOUT Funds earmarked for outgoing payouts
PLATFORM_COMMISSION Fynex platform fee collection wallet
TAX Tax reserve wallet
OTHER Custom-purpose wallet
EXTERNAL_SAFEGUARDING_ACCOUNT Funds held in a safeguarding account
FYNEX_OPERATIONAL Internal Fynex operational ledger
EXTERNAL_CREDIT Credit facility wallet

Wallet status can be ACTIVE, INACTIVE, or FROZEN.


GraphQL operations

List all wallets for a seller

query ListWallets($merchantId: ID, $limit: Int, $offset: Int) {
  wallets(merchantId: $merchantId, limit: $limit, offset: $offset) {
    id
    name
    type
    status
    currencyCode
    currencyScale
    isSystem
    createdAt
    snapshot {
      availableBalanceMinor
      heldBalanceMinor
      pendingBalanceMinor
      updatedAt
    }
  }
}

Get a single wallet with ledger entries

query GetWallet($id: Int!, $entryLimit: Int, $entryOffset: Int) {
  wallet(id: $id) {
    id
    name
    type
    status
    currencyCode
    currencyScale
    snapshot {
      availableBalanceMinor
      heldBalanceMinor
      pendingBalanceMinor
    }
    entries(limit: $entryLimit, offset: $entryOffset) {
      id
      entrySeq
      direction
      kind
      amountMinor
      availableDeltaMinor
      heldDeltaMinor
      balanceBeforeMinor
      balanceAfterMinor
      occurredAt
    }
  }
}

Type reference

Wallet

Field Type Description
id Int! Numeric wallet ID
payeeId Int! Payee this wallet belongs to
sellerAccountId Int! Owning seller account
type WalletType! Wallet role (see table above)
status WalletStatus! ACTIVE, INACTIVE, or FROZEN
name String! Human-readable label
currencyCode CurrencyCode! ISO 4217 currency code
currencyScale Int! Decimal scale (e.g. 2 for EUR meaning amounts are in cents)
isSystem Boolean! true for Fynex-managed system wallets
createdAt Time! Creation timestamp
snapshot WalletBalanceSnapshot Latest balance snapshot
withdrawableBalanceMinor Int! Part of available a payout can take now — see Withdrawable vs. maturing
maturingBalanceMinor Int! Settled funds still inside the payout maturity hold
entries [WalletEntry!]! Paginated ledger entries
payoutMethod PayoutMethod Associated payout method if any

WalletBalanceSnapshot

The snapshot is updated after each ledger write and represents the current balance at the time of the last entry.

Field Type Description
availableBalanceMinor Int! Spendable balance in minor currency units
heldBalanceMinor Int! Funds reserved against an in-flight payout or currency conversion; released back to available if it fails, is cancelled or is rejected. Not the payout maturity hold — see below
pendingBalanceMinor Int! Legacy field; stays 0. Read maturingBalanceMinor on the wallet instead
lastEntrySeq Int! Sequence number of the entry that produced this snapshot
updatedAt Time! When the snapshot was last written

Withdrawable vs. maturing

Settled funds count in availableBalanceMinor straight away, but each settlement or split leg is held for T+N business days before it can be paid out — N is the seller's payoutHoldDays (3 by default; see Splits). Two fields on the wallet (REST GET /wallets and the GraphQL Wallet type) show that hold:

Field Meaning
withdrawableBalanceMinor The part of availableBalanceMinor a payout can take now. Check this, not availableBalanceMinor, before creating a payout.
maturingBalanceMinor Settled funds still inside the maturity hold: counted in available, not yet withdrawable.

Usually withdrawableBalanceMinor + maturingBalanceMinor == availableBalanceMinor, but withdrawable is floored at 0, so after a debit that takes available below the maturing sum the two no longer add up — do not rely on the equality.

All balance amounts are in minor currency units (e.g. cents for EUR/USD). Divide by 10^currencyScale to get the decimal amount.

WalletEntry

Each entry is an append-only record of a balance movement.

Field Type Description
id Int! Entry ID
entrySeq Int! Monotonically increasing per-wallet sequence
direction WalletEntryDirection! DEBIT or CREDIT
kind WalletEntryKind! Cause: PAYMENT, PAYOUT, SPLIT_EXECUTION, MANUAL_ADJUST, INCOMING_PAYMENT_PROCESSED, OUTGOING_PAYMENT_PROCESSED
amountMinor Int! Movement amount in minor units
balanceBeforeMinor Int! Available balance before this entry
balanceAfterMinor Int! Available balance after this entry
heldDeltaMinor Int! Change in held balance
occurredAt Time! When the movement occurred
transferId Int Linked WalletTransfer ID if this entry resulted from an inter-wallet movement
reconciledAt Time Set when the entry is reconciled

WalletTransfer

A transfer records an inter-wallet movement (e.g. when a split rule distributes funds from the main wallet to a payee wallet).

Field Type Description
id Int! Transfer ID
type String! Transfer type
status String! Current status
sourceWalletId Int! Origin wallet
destinationWalletId Int Target wallet (if intra-Fynex)
destinationPayoutMethodId Int Target payout method (if external)
sourceAmountMinor Int! Amount debited from source
destinationAmountMinor Int! Amount credited to destination
sourceCurrencyCode CurrencyCode! Source currency
destinationCurrencyCode CurrencyCode! Destination currency
splitExecutionId Int Linked split execution if applicable
requestedAt Time When the transfer was requested
postedAt Time When the transfer was posted
errorCode String Present if the transfer failed

Code samples

curl

# Step 1 — login and save the cookie
curl -sc cookies.txt \
  -X POST https://api.fynex.ai/api/v1/login/dashboard \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "your_password"}'

# Step 2 — list wallets for a seller account
curl -b cookies.txt \
  -X POST https://api.fynex.ai/dashboard/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query ListWallets($merchantId: ID, $limit: Int, $offset: Int) { wallets(merchantId: $merchantId, limit: $limit, offset: $offset) { id name type status currencyCode snapshot { availableBalanceMinor heldBalanceMinor pendingBalanceMinor updatedAt } } }",
    "variables": { "merchantId": "42", "limit": 20, "offset": 0 }
  }'

JavaScript

const BASE = 'https://api.fynex.ai';

async function login(email, password) {
  const res = await fetch(`${BASE}/api/v1/login/dashboard`, {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password }),
  });
  if (!res.ok) throw new Error(`Login failed: ${res.status}`);
}

async function gql(query, variables = {}) {
  const res = await fetch(`${BASE}/dashboard/graphql`, {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ query, variables }),
  });
  const { data, errors } = await res.json();
  if (errors?.length) throw new Error(errors[0].message);
  return data;
}

await login('you@example.com', 'your_password');

const { wallets } = await gql(
  `query ListWallets($merchantId: ID, $limit: Int, $offset: Int) {
     wallets(merchantId: $merchantId, limit: $limit, offset: $offset) {
       id
       name
       type
       status
       currencyCode
       snapshot {
         availableBalanceMinor
         heldBalanceMinor
         pendingBalanceMinor
         updatedAt
       }
     }
   }`,
  { merchantId: '42', limit: 20, offset: 0 }
);

for (const w of wallets) {
  const scale = Math.pow(10, 2); // adjust if currencyScale != 2
  console.log(
    `${w.name} (${w.currencyCode}): ${w.snapshot.availableBalanceMinor / scale} available`
  );
}

Python

import requests

BASE = "https://api.fynex.ai"
session = requests.Session()

# Step 1 — login
session.post(
    f"{BASE}/api/v1/login/dashboard",
    json={"email": "you@example.com", "password": "your_password"},
).raise_for_status()

# Step 2 — list wallets
query = """
  query ListWallets($merchantId: ID, $limit: Int, $offset: Int) {
    wallets(merchantId: $merchantId, limit: $limit, offset: $offset) {
      id
      name
      type
      status
      currencyCode
      currencyScale
      snapshot {
        availableBalanceMinor
        heldBalanceMinor
        pendingBalanceMinor
        updatedAt
      }
    }
  }
"""

resp = session.post(
    f"{BASE}/dashboard/graphql",
    json={"query": query, "variables": {"sellerAccountId": 42, "limit": 20, "offset": 0}},
)
resp.raise_for_status()
result = resp.json()
if "errors" in result:
    raise RuntimeError(result["errors"][0]["message"])

for wallet in result["data"]["wallets"]:
    scale = 10 ** wallet["currencyScale"]
    available = wallet["snapshot"]["availableBalanceMinor"] / scale
    print(f'{wallet["name"]} ({wallet["currencyCode"]}): {available:.2f} available')

Use cases

Check available balance before requesting a payout. Query the wallet's snapshot.availableBalanceMinor, convert to decimal using currencyScale, and compare against the desired payout amount. If availableBalanceMinor is insufficient, the payout request will be rejected.

Reconcile balances against your own ledger. Fetch entries with limit/offset pagination, ordering by entrySeq. Each entry's balanceAfterMinor should match your internal running balance. Use reconciledAt to distinguish entries already reconciled by Fynex.

Caution

Balance amounts are always in minor currency units (e.g. cents). A value of 12345 with currencyScale: 2 equals 123.45 in the nominal currency. Never display raw minor-unit amounts to end users without dividing by 10^currencyScale.

See also

  • GraphQL Authentication — How to obtain the dashboard_session cookie required for all GraphQL calls.
  • Reconciliation — Match Fynex settlement records against your own books.
  • Payouts — Request a wallet-to-payee transfer via REST or GraphQL.