Accounting
- 1 endpoint
Export accounting data#
GET /accounting/
Exports the request's space's accounting events of a range of days, ordered by transaction time: as JSON (one page: hasMore false) or as a CSV file (the same keys as columns, in AccountingEvent's order).
- Auth
- X-API-Key: any key
- On-Behalf-Of
- Honored: acts in the member's space
- Idempotency-Key
- Ignored
- Success
- 200
request.sh
curl "https://api.qbitflow.app/v2/accounting/export?from=2026-01-01&to=2026-03-31&format=json" \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: an array of AccountingEvent (format=csv: CSV text)// Every payment, bill, refund and fee between two dates (both included). Any range: the SDK// requests it in windows of at most 92 days, both included (here 4), and concatenates them.const rows = await client. accounting. exportJsonRange( '2026-01-01', '2026-12-31');for (const row of rows.slice(0, 5)) { console.log(row.type, row.txUuid, row.txTimeUtc, row.grossAmountUsd, row.productName);} // The same as CSV text, its header line once.const csv = await client. accounting. exportCsvRange( '2026-01-01', '2026-12-31');await writeFile('qbitflow-2026.csv', csv, { mode: 0o600 });# The API exports at most 92 days at a time (both included): the *_range methods split any# range into windows, request them in order and join the results (the CSV header once).events = client. accounting. export_json_range( "2026-01-01", "2026-12-31")for event in events: print(event.type, event.tx_uuid, event.tx_time_utc.date(), event.gross_amount_usd) csv_text = client. accounting. export_csv_range( "2026-01-01", "2026-12-31")with open("qbitflow-2026.csv", "w", encoding="utf-8") as file: file.write(csv_text)// The API exports at most 92 days at a time (both included): the …Range methods split any// range into windows, request them in order and join the results (the CSV header once).events, err := client. Accounting. ExportJSONRange( ctx, "2026-01-01", "2026-12-31")if err != nil { log.Fatal(err)}for _, e := range events { fmt.Println(e.Type, e.TxUUID, e. TxTimeUTC. Format( time. DateOnly), e.GrossAmountUSD, e.ProductName)} csv, err := client. Accounting. ExportCSVRange( ctx, "2026-01-01", "2026-12-31")if err != nil { log.Fatal(err)}if err := os. WriteFile( "qbitflow-2026.csv", []byte(csv), 0o600); err != nil { log.Fatal(err)}// The API exports at most 92 days at a time (both included): the range helpers split any range// into windows, request them in order and join the results (the CSV header once).$events = $client->accounting->exportJsonRange( '2026-01-01', '2026-12-31');foreach ($events as $event) { echo "{$event->type} {$event->txUuid} {$event->txTimeUtc->format('Y-m-d')} {$event->grossAmountUsd} USD {$event->productName}\n";} $csv = $client->accounting->exportCsvRange( '2026-01-01', '2026-12-31'); // one header line, then the rowsQuery parameters
fromstringRequiredThe first day (YYYY-MM-DD, UTC)
dateformattostringRequiredThe last day (YYYY-MM-DD, UTC), included; at most 92 days after from, both included
dateformatformatstringRequiredjson: the rows in one page (a bounded list); csv: a file, one row per event
oneof=csv json
Response
A page: { "items": AccountingEvent[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.
49 fields of each AccountingEvent
txTimeUtcstringtypestringpayment, bill, refund, organizationFee or referralFee
referencestringOptionalThe payment's reference (the merchant's), when it has one
productNamestringOptionalcustomerReferencestringOptionalgrossAmountUsdstringOptionalWhat the customer paid (a refund: what went back, negative)
platformFeeUsdstringOptionalQBitFlow's fee, the referrer's share included; absent when none (a refund)
referralFeeUsdstringOptionalThe referrer's share of the platform fee; absent when no referral applied
organizationFeeUsdstringOptionalThe organization's fee on a member's payment; absent when none
netAmountUsdstringOptionalWhat the merchant received (a payment or a bill: after the fees) or sent back (a refund: the refunded amount, negative)
chainstringcurrencystringWhat was paid, as markets name it: the token (USDC) or the chain's native currency (ETH, SOL)
currencyDecimalsintegerThe currency's decimals: an amount × 10^currencyDecimals is its min units on-chain
currencyPriceUsdstringOptionalThe currency's USD price the amounts were converted at: grossAmountUsd / grossAmount, to 8 decimals (the original payment's or bill's on a refund). Absent without a gross amount
grossAmountstringOptionalgrossAmountMinUnitsstringOptionalEach amount's twin …MinUnits is the same amount on-chain: an integer string (JSON), × 10^-currencyDecimals = the amount
platformFeestringOptionalQBitFlow's fee, the referrer's share included
platformFeeMinUnitsstringOptionalreferralFeestringOptionalThe referrer's share, paid out of the platform fee: what a referralFee event earned. Absent when no referral applied (none, or past its deadline)
referralFeeMinUnitsstringOptionalorganizationFeestringOptionalAbsent when none
organizationFeeMinUnitsstringOptionalnetAmountstringOptionalnetAmountMinUnitsstringOptionalnetworkFeesPaidBystringOptionalpayer (a payment or a bill: on top of the amount), merchant (a refund the space sent) or organization (a refund of a payment the organization held for its member, sent from its wallet)
One of:
payerA payment or a bill: the payer, on top of the amountmerchantA refund the space sent from its walletorganizationA refund of a payment the organization held for its member, sent from the organization's wallet
networkFeesstringOptionalIn networkFeesCurrency's units. Absent when not recorded (records made before they were)
networkFeesMinUnitsstringOptionalIn networkFeesCurrency's min units
networkFeesCurrencystringOptionalWhat paid them: the currency on a payment or a bill (the payer's gas refund, taken in it), the chain's native currency (ETH, SOL) on a refund
networkFeesCurrencyDecimalsintegerOptionalnetworkFeesCurrency's decimals
networkFeesCurrencyPriceUsdstringOptionalnetworkFeesCurrency's USD price networkFeesUsd was converted at. Absent when unknown (a refund recorded before it was)
networkFeesUsdstringOptionalAbsent when unknown
platformFeePercentstringOptionalQBitFlow's fee rate on the event
referralFeePercentstringOptionalThe referrer's share of the platform fee ("20" = 20 % of it), when a referral applied
organizationFeePercentstringOptionalThe organization's fee rate on the event, when it took one
fromAddressstringOptionalAbsent on referralFee rows
toAddressstringOptionalAbsent on referralFee rows
txHashstringOptionalAbsent on referralFee rows
blockNumberOrSlotstringOptionaltokenContractOrMintstringOptionalThe token's contract (EVM) or mint (Solana); absent for a native currency
explorerUrlstringOptionalAbsent on referralFee rows
receiptUrlstringOptionalThe transaction's page for its customer (the payment, bill or refund, as the customer's management link shows it: public, by its uuid). Absent on referralFee rows
txUuidstringOptionalThe event's transaction, prefixed by its type: pay@ (a payment), sub-hist@ (a bill), refund@ (a refund); absent on referralFee rows
productUuidstringOptionalAbsent when the event has no product
productReferencestringOptionalproductDescriptionstringOptionalcustomerUuidstringOptionaluserUuidstringOptionalThe member whose space the event is in; absent for the organization's own
With format=csv: CSV text (Content-Type: text/csv), as an attachment.
Errors
The common codes only, as any route (what each means):
- 400validation_failed
- 401unauthorized
- 403forbidden
- 403policy_disabled
- 404not_found
- 429rate_limit_exceeded
- 500internal
- 504timeout
Edge cases
The contract's rules for these routes: Query parameters & validation · Output · Scoping.
Read all 3
Query parameters & validation
fromandtoare required and must beYYYY-MM-DD(dateformat); a missing or malformed value →400validation_failedon its name.formatis required and must beoneof=csv json; any other value →400validation_failedonformat.- The window is at most 92 days,
fromandtoincluded (about 3 months): a longer one →400validation_failedonto, withdetails.max: 92.tobeforefrom→400validation_failedonto. (bad_requestis no longer answered.) - The dates are the transactions', in UTC, both days included: an event is in the export of the day its transaction's block was mined (
txTimeUtc), whenever QBitFlow recorded it (a payment mined at 23:59:50 and recorded after midnight is that day's). An event recorded without its block counts at its record's time (a payment's or a bill's recording, a refund's approval), which is then itstxTimeUtc. So consecutive exports never miss nor repeat an event.
Output
format=json→200withContent-Type: application/json: a bounded list, the{items, hasMore, nextCursor}envelope (pagination) in one page: everyAccountingEventof the window initems([]when there is nothing in range),hasMore: false, nonextCursor(limitandcursoraren't read: the window bounds the export).format=csv→200withContent-Type: text/csvandContent-Disposition: attachment; filename="qbitflow_<from>_to_<to>.csv"; the body always is the header row (columns from thecsv:"..."tags) followed by one row per event, and nothing else (nothing in range → only the header row). A failure while reading the data is the normal JSON error envelope, without the CSV headers. The handler's return type only describes the JSON format.- Events are ordered by
txTimeUtc, thentype, thentxUuid: the same order on every export.txTimeUtcis always in UTC (Z). - The export is flat, for spreadsheets: one column per key, the same keys in JSON and CSV. It is the documented exception to the currency object (naming): the currency is named by
currency(its symbol),chainandcurrencyDecimals, never nested. - CSV columns are in reading order, the field order of
AccountingEventabove: what happened and when (txTimeUtc…customerReference), the USD amounts from gross to net (grossAmountUsd…netAmountUsd), the same amounts in the currency paid, each followed by its min units (chain…netAmountMinUnits), the network fees (networkFeesPaidBy…networkFeesUsd), the rates (platformFeePercent…organizationFeePercent), the on-chain proof (fromAddress…receiptUrl), then the ids (txUuid…userUuid). Read a column by its header name, not its position. - Every amount is a decimal string in JSON (
"7.5","-100"; naming) and a plain number in CSV. Amounts are in the currency's units (7.5USDC,0.1ETH), exact; each currency amount has its…MinUnitstwin, the same amount on-chain as an integer string (grossAmountMinUnits,platformFeeMinUnits,referralFeeMinUnits,organizationFeeMinUnits,netAmountMinUnits,networkFeesMinUnits): an amount × 10^decimals is its min units.currencyis what was paid, as markets name it: the token (USDC) or the chain's native currency (ETH,SOL; Base's isETH, itschainBASE). Always set, a native currency's too.tokenContractOrMintis absent (an empty cell) for a native currency.currencyDecimalsis its decimals.currencyPriceUsdis the currency's USD price the amounts were converted at,grossAmountUsd / grossAmount(8 decimals): the payment's or the bill's at its time; on a refund, the refunded transaction's (a refund is valued at what was paid, not at the day it was sent). Absent (an empty cell) without a gross amount.
- No value is no key (naming): a value the row doesn't have is absent from JSON (never
null,""or0) and an empty cell in CSV (the column is always there). That is: a fee that doesn't apply (organizationFee*without an organization fee,referralFee*without a referral or past its deadline,platformFee*on a refund), its rate (…Percent), an amount not known (network fees not recorded, a price not recorded), andreference,relatedTxUuid/relatedReference(refunds only),productUuidand the otherproduct*fields (no product),customerUuid/customerReference(no customer),userUuid(the organization's own events). - CSV cells are never formulas. A cell starting with
=,+,-,@, a tab or a carriage return (a product, customer or reference text a member or a payer chose) is written with a leading single quote, so a spreadsheet shows it as text instead of running it: a product named=HYPERLINK("…")exports as'=HYPERLINK("…"). Numbers stay numbers (a refund's-12.5). JSON is unchanged. platformFeePercent,referralFeePercentandorganizationFeePercentare the rates charged on the event, percent strings ("1.5"= 1.5 %), the same in JSON and CSV; absent when the fee doesn't apply.customerReferenceis the merchant's reference of the customer: the one its checkout was given (customerReference, kept on the payment, the subscription and each bill, with or without a customer at QBitFlow), else its customer'sreference. A refund takes its payment's or bill's.- Amounts are the on-chain split (
settlement.split), never recomputed from the rates:platformFee/platformFeeUsdis what the merchant paid QBitFlow, the referrer's share included (the contracts pay it out of the platform fee), sogrossAmount = platformFee + organizationFee + netAmountexactly (an absent fee counting0), in the currency and in USD:grossAmountUsdis what was charged, andnetAmountUsdthe rest once the fees are taken (on records whose USD parts were each rounded on their own,netAmountUsdmay differ from the merchant's recorded share by a micro-dollar; the currency amounts are exact). A payment or bill recorded without its split makes the export fail (500) rather than show no fees. So does a refund whose payment or bill can't be read: never a row without its currency. - A refund's net is the refunded amount:
netAmount/netAmountUsdequalgrossAmount/grossAmountUsd(negative), what left the wallet that sent it (QBitFlow's and the organization's fees aren't refunded: its fee columns are absent). A refund sends back a share of what the customer paid, the network fees they paid on top included (refundPercentofpaidMinUnits, Refunds): a full refund'sgrossAmountis the payment'sgrossAmountplus itsnetworkFees. - Network fees are never part of the net.
networkFeesis the transaction's network fees innetworkFeesCurrency's units (its decimalsnetworkFeesCurrencyDecimals, its min unitsnetworkFeesMinUnits),networkFeesUsdthe same atnetworkFeesCurrencyPriceUsd, andnetworkFeesPaidBywhose wallet paid them:payeron a payment or a bill (and anorganizationFeerow): the customer paid them on top of the amount, so they are not the merchant's cost. They are in the event's own currency (the gas refund the contracts took in it):networkFeesCurrency=currency, atcurrencyPriceUsd. Absent on records made before they were recorded ("0"when recorded as none).merchanton a refund the space sent from its wallet: a cost of the merchant's, to book apart. They are in the chain's native currency (ETH,SOL), not the refunded token, at its price when the refund was recorded (networkFeesCurrencyPriceUsd; it andnetworkFeesUsdare absent on refunds recorded before it was).networkFeesis absent on refunds recorded before their fees were (unknown).organizationon a refund of a payment the organization held for its member: the organization's wallet sent it (and paid its fees), in the native currency as above. The row is in the member's export.
- Each
AccountingEventtypeis one ofpayment,bill(a subscription's bill),refund,organizationFeeorreferralFee.txUuidis the event's transaction id with its type's prefix:pay@(a payment, an organization fee's),sub-hist@(a bill),refund@(a refund). A refund names what it refunded byrelatedTxUuid(pay@…orsub-hist@…) and, for a payment, itsrelatedReference(a bill has no reference: absent).referenceis the payment's own reference (absent without one). organizationFeeandreferralFeeevents are the exporter's income from another space's payment or bill (in the requested dates, like every event):organizationFee: the fees the organization earned on its members' payments. Only the organization's export has them; a member's export never does.referralFee: the fees earned by the exporter's own referral (its organization's, or the member's), none without one.- An
organizationFeeevent carries the full detail of its member's payment or bill (gross amount, split, product, customer, chain data), with the fee type, so the fee can be reconciled. The fee earned is itsorganizationFee/organizationFeeUsdcolumns. Its addresses are the payment's (toAddressis the wallet paid: the member's, or the organization's for a payment it held), not where the fee went (the organization's wallet). - A
referralFeeevent is another organization's payment or bill: it only tells what the referrer earned, when and on which chain. It hastype,txTimeUtc,chain,blockNumberOrSlot,currency,currencyDecimals,currencyPriceUsd,tokenContractOrMint,referralFeePercent,referralFeeUsd,referralFeeandreferralFeeMinUnits(the fee earned), and nothing else: every other field (txUuid,receiptUrl,txHash,explorerUrl, the addresses, the product and customer fields, the payment's amounts and everynetworkFees*column) is absent from JSON and an empty cell in CSV.
referralFeePercent,referralFeeUsdandreferralFeeare the referrer's share of the platform fee (it is included inplatformFee): the rate that applied ("20"= 20 % of the platform fee) and the amounts paid. Absent when no referral applied, including a referral past its deadline.
Scoping
- Results are the request's space's (spaces), in its mode: the organization's export, or a member's (their session or key,
On-Behalf-Of, or the dashboard switched into their space). An export never includes another organization's events. - An export is the space's ledger (its payments, bills, refunds and the fees it earned), not a wallet's: the organization's export doesn't show the funds it holds for its members (recorded in the member's space, the organization earning its
organizationFee), their releases to the members, nor the refunds of held payments it sent (in the member's export,networkFeesPaidBy: organization).
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)