API reference

Wallets

  • 3 endpoints

Wallets belong to a space (spaces): the organization's shared space or a member's personal space, in one mode. A space has at most one wallet per chain (main currency); the wallet receives the chain's native currency and the tokens enabled on it (tokenWallets).

The v1 paths (/wallet/*) and their v2 names are in MIGRATION.md § Routes.

List your wallets#

GET /wallets

Lists the wallets of the caller's space, in one page, with their balances on withBalances=true (a balance the chain didn't answer is absent).

Auth
X-API-Key: any key
On-Behalf-Of
Honored: acts in the member's space
Idempotency-Key
Ignored
Success
200
Request

request.sh

curl https://api.qbitflow.app/v2/wallets \  -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of WalletWithBalance ({ items, hasMore: false })

Query parameters

  • withBalancesbooleanOptional

    true: each currency a wallet accepts with its balance, read on its chain (slower). Default false

Response

A page: { "items": WalletWithBalance[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.

  • uuidstring

    Its only id (a UUIDv7)

  • createdAtstring
  • addressstring

    The wallet's address on its chain (EVM: 0x…, Solana: base58)

  • testboolean

    Whether this is test data (testnets) or live data

  • userUuidstringOptional

    Member the resource belongs to; omitted for the organization's own resources

    Only for the resource's owner

  • currencyIdinteger

    The chain, by its native coin, written as the currency object under currency (GET /currencies/:id)

  • tokenWalletsarray of TokenWalletWithBalance

    The currencies it accepts, each with its balance (absent when the chain couldn't be read)

    5 fields of each TokenWalletWithBalance
    • uuidstring

      Its only id (a UUIDv7)

    • createdAtstring

      When the wallet started accepting it

    • currencyIdinteger

      The currency accepted, written as the currency object under currency (GET /currencies/:id)

    • walletUuidstring

      The wallet it belongs to

    • balanceBalanceOptional

      What the wallet holds of the currency; absent when the chain couldn't be read

      4 fields of Balance
      • currencyIdinteger

        The currency held, written as the currency object under currency (GET /currencies/:id)

      • amountstring

        In the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")

      • amountMinUnitsstring

        The on-chain integer, in the token's smallest unit, a string of digits ("12500000")

      • amountUsdstringOptional

        Its value in USD, a decimal string; absent when no price was known

Get accepted currencies#

GET /wallets/accepted-currencies

Lists the currencies a space's payments can be made in, in the caller's mode, in one page: exactly what its checkouts offer. Any role reads its own space's; an owner or admin also a member's (?userUuid).

Auth
X-API-Key: any key
On-Behalf-Of
Honored: acts in the member's space
Idempotency-Key
Ignored
Success
200
Request

request.sh

curl https://api.qbitflow.app/v2/wallets/accepted-currencies \  -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Currency ({ items, hasMore: false })

Query parameters

  • userUuidstringOptional

    Optional: a member of the caller's organization (owners and admins: 403 otherwise; 404 for anyone else). Defaults to the caller's space

Response

A page: { "items": Currency[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.

9 fields of each Currency
  • idinteger

    The currency's id (a public catalog: ids reveal nothing)

  • codestring

    What requests name it by: CHAIN:TOKEN for a token ("BASE:USDC"), the chain's symbol for its native coin ("ETH")

  • symbolstring

    Its symbol ("USDC", "ETH")

  • namestring

    Its full name ("USD Coin", "Ethereum")

  • chainstring

    The chain it is on: its native coin's symbol ("ETH", "BASE", "SOL")

  • decimalsinteger

    The decimals of its on-chain amounts (min units = amount × 10^decimals)

  • addressstringOptional

    A token's contract address (EVM) or mint (Solana); absent on a native coin

  • mainCurrencyIdintegerOptional

    A token's chain: its native coin's id; absent on a native coin

  • testboolean

    A test network's currency (true) or a live one (false)

List a member's wallets#

GET /members/:userUuid/wallets

Lists a member's wallets in the caller's mode, in one page. A user who isn't a member of the caller's organization is 404, whether or not they have wallets.

Auth
X-API-Key: an admin key
On-Behalf-Of
Refused: the admin role is needed
Idempotency-Key
Ignored
Success
200
Request

request.sh

curl "https://api.qbitflow.app/v2/members/$MEMBER_UUID/wallets" \  -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Wallet ({ items, hasMore: false })
// Where the member is paid. Without a wallet, their checkouts answer 409 merchant_not_ready.const wallets = await client.wallets.listForMember(memberUuid);for (const wallet of wallets) {	console.log(`${wallet.currency.chain}: ${wallet.address}`);}
for wallet in client.wallets.list_for_member(member_uuid):    print(wallet.currency.chain, wallet.address)
wallets, err := client.Wallets.ListForMember(ctx, memberUUID)if err != nil {	log.Fatal(err)}for _, w := range wallets {	fmt.Println(w.Currency.Chain, w.Address)}
foreach ($client->wallets->listForMember($memberUuid) as $wallet) {	echo "{$wallet->currency->chain} {$wallet->address}\n";}

Path parameters

  • userUuidstringRequired

Response

A page: { "items": Wallet[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.

  • uuidstring

    Its only id (a UUIDv7)

  • createdAtstring
  • addressstring

    The wallet's address on its chain (EVM: 0x…, Solana: base58)

  • testboolean

    Whether this is test data (testnets) or live data

  • userUuidstringOptional

    Member the resource belongs to; omitted for the organization's own resources

    Only for the resource's owner

  • tokenWalletsarray of TokenWallet

    The currencies it accepts on its chain (always present, [] when none)

    4 fields of each TokenWallet
    • uuidstring

      Its only id (a UUIDv7)

    • createdAtstring

      When the wallet started accepting it

    • currencyIdinteger

      The currency accepted, written as the currency object under currency (GET /currencies/:id)

    • walletUuidstring

      The wallet it belongs to

  • currencyIdinteger

    The chain, by its native coin, written as the currency object under currency (GET /currencies/:id)

Edge cases

The contract's rules for these routes: Access · The wallet and the token wallet · Read · Delete.

Read all 4

Access

  • Reads an integrator needs are open to API keys (SDK): GET /wallets, GET /wallets/accepted-currencies and GET /members/:userUuid/wallets: it checks a seller is ready before opening their checkouts. Every other route is dashboard-only (GET /handles/:handle/currencies is also public): an API key (with or without On-Behalf-Of) → 404.
  • GET /organization/wallets and GET /members/:userUuid/wallets need an owner or admin in the space: a member (or the team acting as one) → 403.
  • GET /wallets/accepted-currencies is open to every role for the request's own space: a member reads what their own checkouts accept. With ?userUuid=, only an owner or admin (organization key included) reads a member's: anyone else → 403 forbidden.
  • ?userUuid= (on /wallets/available-currencies, /wallets/accepted-currencies) and /members/:userUuid/wallets name a member of the caller's organization by their user uuid, in the caller's mode. A user of another organization, an unknown uuid, or the caller's own as an owner or admin (who has no personal space) → 404, whether or not that user has wallets. A malformed uuid → 400 validation_failed on userUuid.
  • Only a wallet's owner changes it (POST /wallets, DELETE /wallets/:uuid, POST /token-wallets, DELETE /token-wallets/:uuid, and a recent re-authentication): where payments and releases go is theirs to decide alone.
    • A member's wallets (and an admin's own personal space's) are changed by that person only. The team acting in the member's space (a switch into it) → 403 forbidden, nothing changed: the organization never replaces a seller's payout wallet.
    • The organization's wallets (its shared space's) are changed by its owner only; an admin → 403 forbidden.
    • Reading is unchanged: the team still lists a member's wallets and the organization's.

The wallet and the token wallet

  • Wallet: uuid, createdAt, address (it was publicKey), currency (the chain's native coin, the currency object of naming: it was currencyId + a full currency with a nested mainCurrency), test, userUuid (a member's only), tokenWallets (always present, [] when none).
  • TokenWallet (a currency the wallet accepts: a token or the chain's native coin): uuid, createdAt, currency (the accepted currency's object: it was tokenId + token), walletUuid.
  • Wallets and token wallets are named by their uuid; currencies keep their numeric id inside the currency object.

Read

  • GET /wallets: the session's space's wallets, in one page (the list envelope with hasMore: false, pagination). ?withBalances=true adds each token wallet's balance, read on its chain (slower); a balance the chain didn't answer is absent (it was a zero-valued object). GET /organization/wallets: the organization's (shared space's) wallets in the session's mode; GET /members/:userUuid/wallets: a member's. Both in one page.
  • GET /wallets/available-chains: the chains the space can still add a wallet on; GET /wallets/available-currencies: every currency (chains and tokens) it can still enable; GET /token-wallets/available-tokens?chain=<code>: the same, for one chain (chain required, a chain's code: a token's or an unknown code → 400 on chain). All apply the currency rule, in one page.
  • GET /wallets/accepted-currencies and GET /handles/:handle/currencies (public, qbf.cash): the currencies the space's payments can be made in, the ones enabled on the wallets that receive them (the organization's while it holds the member's funds), within the currency rule: a member doesn't offer one the organization dropped after the member enabled it. A checkout's availableCurrencies are these. In one page. An unknown handle → 404; a malformed one → 400 on handle.
  • GET /wallets/balance?currency=<code>: what the session's own wallet on that currency's chain holds of that currency (currency required, at most 100 characters; unknown → 400 on currency; no wallet on its chain → 404): { "currency": {…}, "amount": "12.5", "amountMinUnits": "12500000", "amountUsd": "12.5" }: the amount in the currency's units (exact), its on-chain integer (a string of digits), and its USD value at today's price (6 decimals; absent when QBitFlow has no price it can trust). It was { currency: "BASE:USDC", balance, balanceUsd: <number> }, and read the chain's native coin whatever the currency asked.

Delete

  • DELETE /wallets/:uuid deletes a wallet of the session's space and its token wallets → 204 with no body (it answered a message). Only the wallets' owner reaches it (RequireWalletOwner, checked before the wallet is looked up): an admin (in the organization's space, or acting in a member's) or the owner acting in a member's space → 403 forbidden, whatever the uuid. For whoever passes it (a member in their own space, the owner in the organization's), a wallet outside the session's space (another member's, the organization's, a member's for the owner, another organization's) or an unknown uuid → 404, and it is kept. A malformed uuid → 400 on uuid. Refused while live subscriptions pay its address (409 wallet_has_active_subscriptions, details.activeSubscriptions) or, the organization's live wallet, while it holds members' funds on its chain (409 held_funds_pending, details.heldEntries). The organization's wallet deleted, its members stop accepting its currencies.
  • DELETE /token-wallets/:uuid removes a currency from one of the session's space's wallets → 204; any other token wallet → 404 and it is kept (owning a wallet on the same chain is not enough). The organization's removed, its members stop accepting it too (their checkouts open since refuse it: 409 currency_not_accepted); running subscriptions keep paying.

The codes named here

  • 400validation_failed

    path/query/body failed binding or validation, or a business rule about one input (a field named in errors)

  • 403forbidden

    authenticated but not allowed (role, peer resource)

  • 409held_funds_pending

    removing a member (DELETE /members/:userUuid, DELETE /team/:userUuid for an admin who kept a personal space), or closing an organization, while the organization holds a member's live funds: release them first (Members and held funds); deleting the organization's live wallet of a chain (DELETE /wallets/:uuid) while it holds members' live funds in that chain's currencies, which their release is paid from (Wallets)