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 individualWalletEntryrows andWalletTransferrecords. 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 itThe REST surface uses your
Authorization: Bearer <seller_token>(no cookie), is seller-scoped, hides Fynex system wallets, and returns balances asavailableBalanceMinor/heldBalanceMinor/pendingBalanceMinor/totalBalanceMinor, pluswithdrawableBalanceMinor/maturingBalanceMinorfor 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
12345withcurrencyScale: 2equals 123.45 in the nominal currency. Never display raw minor-unit amounts to end users without dividing by10^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.