Payments and transactions
- 4 endpoints
Payments are created only by completing an on-chain checkout (a checkout session, Checkout sessions): there is no POST creating one directly.
List payments#
GET /payments
Lists the one-time payments of the request's space (with includeMembers, of the organization and its members; with userUuid, of one member), newest first (createdAt, then uuid). With reference, the payment with this reference: 0 or 1 item (one per space read).
- 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/payments \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Payment ({ items, hasMore, nextCursor? })const page = await client.payments.list({ createdAfter: new Date(Date.now() - 30 * 24 * 3600 * 1000), // the last 30 days limit: 10,});for (const payment of page.items) { // Amounts are decimal strings: the token's (amount, in currency) and USD (amountUsd). const { uuid, reference, amount, currency, amountUsd } = payment; console.log(`${uuid} "${reference ?? ''}": ${amount} ${currency.symbol} (${amountUsd} USD)`);}if (page.hasMore) { // Pass it back, verbatim, as the cursor param for the next page. console.log(`next cursor: ${page.nextCursor}`);}page = client. payments. list( refunded=False, limit=20) # newest firstfor payment in page.items: # Amounts are decimal strings: the token's (amount, with currency) and USD (amount_usd). print( payment.uuid, payment.reference, payment.amount, payment.currency.symbol, f"({payment.amount_usd} USD)", )if page.has_more: print("next page: cursor =", page.next_cursor) # pass it back, verbatim, as cursor=since := time.Now().AddDate(0, -1, 0)page, err := client.Payments.List(ctx, &qbitflow.PaymentListParams{ CreatedAfter: &since, // the last month Limit: 20,})if err != nil { log.Fatal(err)}for _, p := range page.Items { // Amounts are decimal strings: the token's (Amount, with Currency) and USD (AmountUSD). fmt.Printf("%s %q: %s %s (%s USD)\n", p.UUID, p.Reference, p.Amount, p.Currency.Symbol, p.AmountUSD)}if page.HasMore { // Pass it back, verbatim, as PaymentListParams.Cursor for the next page. fmt.Println("next cursor:", page.NextCursor)}$page = $client->payments->list(new \QBitFlow\Params\PaymentListParams( createdAfter: new \DateTimeImmutable('-30 days'), limit: 20,));foreach ($page->items as $payment) { // Amounts are decimal strings: the token's (amount, with its currency) and USD (amountUsd). echo "{$payment->uuid} " . ($payment->reference ?? '-') . ": {$payment->amount} {$payment->currency->symbol} ({$payment->amountUsd} USD)\n";}if ($page->hasMore) { $cursor = $page->nextCursor; // pass it back, verbatim, as `cursor` for the next page}Also: Iterate over every page
Query parameters
limitintegerOptionalPage size: 20 when absent or ≤ 0, at most 100 (a larger one is clamped, not refused)
cursorstringOptionalThe previous page's nextCursor, verbatim; omit for the first page
max=200customerUuidstringOptionalOnly this customer's
productUuidstringOptionalOnly this product's
createdAfterstringOptionalOnly those created after this instant, excluded (RFC 3339, e.g. 2026-10-04T12:00:00Z, or a date: its midnight UTC)
createdBeforestringOptionalOnly those created before this instant, excluded (RFC 3339 or a date, as createdAfter)
includeMembersbooleanOptionalThe organization's space only (the team, its keys without On-Behalf-Of): its members' too, each naming its member (userUuid). From a member's space → 400 on includeMembers
userUuidstringOptionalThe organization's space only (owners and admins): this member's only, read from the organization's space (a removed member's too). Not with includeMembers (400 on userUuid)
referencestringOptionalOnly the payment with this reference (the merchant's, set on its checkout): 0 or 1 item. References are unique per space: with includeMembers or userUuid, one per space read
referencemax=100refundedbooleanOptionalOnly the payments with (true) or without (false) an approved refund
Response
A page: { "items": Payment[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.
33 fields of each Payment
uuidstringallow read and create, (generated on creation of the payment link)
A prefixed id (pay@…, sub@…)
createdAtstringfromstringtostringamountstringThe amount in the currency's units, exact, a decimal string ("10" for 10 USDC): amountMinUnits / 10^decimals
amountMinUnitsstringThe amount in the currency's smallest unit, a string of digits ("10000000" for 10 USDC, 6 decimals)
amountUsdstringWhat the customer paid, in USD, a decimal string: the price (and, on a one-time payment, the fees its checkout added: fees), which the contracts split between QBitFlow's fee (the referrer's share included), the organization's fee and the merchant (settlement.split). The network fee a customer pays on top (settlement.split.networkFee) is not in it
currencyIdintegerThe currency paid in, written as the currency object under currency (GET /currencies/:id)
txHashstringHash of the transaction in the blockchain
chainstringOptionalThe chain it was paid on: ETH (Ethereum), BASE (Base) or SOL (Solana), the testnet's for a test-mode transfer (currency.test)
explorerUrlstringOptionalIts transaction on the chain's block explorer (the testnet's in test mode). Omitted without a txHash
testbooleanWhether this is test data (testnets) or live data
userUuidstringOptionalMember the resource belongs to; omitted for the organization's own resources
Only for the resource's owner
referencestringOptionalThe merchant's reference for the payment (an order or invoice id), set when creating its checkout. Only for the merchant: never in the public reads by uuid (GET /hosted/transactions/:txUuid)
Only for the resource's owner
priceUsdstringOptionalPriceUSD is the product's price in USD, as the checkout had it, a decimal string, always present: amountUsd is the price plus the fees' lines. (A payment recorded before checkouts had fees has none stored: its price is its amount, Complete.)
feesarray of FeeLineWhat the checkout added to the price, line by line, as the customer saw them (a tax, shipping, the processing fee when the customer paid it); [] without any
4 fields of each
FeeLinetypestringcustom (the merchant's line) or processingFee (QBitFlow's fee, which the merchant has the customer pay)
One of:
customThe merchant's own line: a tax, shipping, a service feeprocessingFeeQBitFlow's fee, which the merchant has the customer pay (computed by QBitFlow)
labelstringThe line's name, as the checkout shows it ("Processing fee" for the processing fee)
descriptionstringOptionalOptional: more about the line, as the merchant wrote it. Omitted without one
amountUsdstringThe line's amount in USD, a decimal string with at most 2 decimals
productNamestringWhat was paid for: the checkout's product name, as it was when the checkout was created (the product's, or the inline one). Later product edits don't change it
productDescriptionstringOptionalSame, for the product's description; absent without one
metadatamapOptionalMetadata is the merchant's own data, copied from the checkout session that created the payment (its metadata), read-only. {} without any. Only for the merchant
Only for the resource's owner
productUuidstringOptionalThe product paid for; omitted when the payment has none (an inline product)
customerUuidstringOptionalThe customer, when QBitFlow has one (named by the checkout, found by its customerReference, or recorded from the details the customer gave); omitted otherwise
Only for the resource's owner
customerReferencestringOptionalThe merchant's reference of the customer, as the checkout was given it (customerReference), whether or not QBitFlow has a customer with it; omitted otherwise
Only for the resource's owner
notestringOptionalA qbf.cash tipper's message to the handle's owner (only for them); omitted without one
Only for the resource's owner
customerSummaryOptionalThe customer, named (merchant only, API reads): who paid, even once deleted. Omitted without one
Only for the resource's owner
6 fields of
SummaryuuidstringThe customer (GET /customers/:uuid)
firstNamestringFirst name
lastNamestringOptionalLast name, when given
emailstringEmail, lowercase
referencestringOptionalThe merchant's reference of the customer, when it has one
deletedbooleanThe merchant deleted the customer: it still names its rows, but GET /customers/:uuid answers 404
settlementSettlementOptionalHow it settled: its fees, its split and its transaction (only for the merchant)
Only for the resource's owner
5 fields of
SettlementfeePercentnumberQBitFlow's fee on this payment, in bps (1 % = 100 bps), deducted from the amount paid. Written as feePercent, a percent string
organizationFeeOrganizationFeeOptionalThe organization's fee on its member's payment (a marketplace's commission), paid to the organization's wallet. It is taken from what remains after QBitFlow's fee (contracts SPEC §4.1): organization = (amount - QBitFlow's fee) × its rate, and the member receives the rest. While the organization holds the member's funds, it is withheld from what the organization owes them instead of paid on-chain. Absent: none
2 fields of
OrganizationFeeaddressstringOptionalThe organization's wallet that receives the fee (only for the merchant)
Only for the resource's owner
feePercentnumberThe organization's fee, in bps, taken from what remains after the platform fee. Written as feePercent, a percent string
referralFeeReferralFeeOptionalThe referrer's share of QBitFlow's fee. Absent: none
2 fields of
ReferralFeeaddressstringOptionalThe referrer's wallet that receives the fee (only for the merchant)
Only for the resource's owner
feePercentnumberThe referrer's share of the platform fee, in bps (2000 = 20 % of it). Written as feePercent, a percent string
splitSplitOptionalHow the contracts split what the payer paid. For a payment the organization held for its member, the organization's fee was withheld from the member's share (not paid on-chain): the split is the one a direct payment would have had. Absent on records made before the split was recorded
5 fields of
SplitplatformTokenAmountQBitFlow's fee (the referrer's share not included)
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
organizationTokenAmountOptionalThe organization's fee; absent without one
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
referralTokenAmountOptionalThe referrer's share of QBitFlow's fee; absent without one
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
merchantTokenAmountWhat the merchant received (the member, for a member's payment), net of every fee
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
networkFeeTokenAmountOptionalNetworkFee is the network fee the payer paid on top of the amount, in the payment's currency: the gas refund the contracts took in the token (their GasRefundProcessed event), or, for a payment in a chain's native coin, the fee of the transaction the payer's wallet paid (its gas and, on Base, its L1 data fee), bounded by what QBitFlow prepared. Not the transaction's own cost to its sender (transaction.fee). Absent on records made before it was recorded ("0" once recorded as none)
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
transactionSettlementTransactionOptionalThe transaction that paid it. Absent before its confirmation
6 fields of
SettlementTransactionblockNumberstringThe block (Ethereum, Base) or slot (Solana) it landed in, a string of digits
blockTimestringOptionalWhen its block was produced (UTC); when it was recorded if the chain's node didn't give it. Absent only on records made before it was recorded
gasUsedintegerOptionalThe gas it consumed (Ethereum, Base). Absent on Solana
feeTokenAmountWhat the transaction cost its sender, in the chain's native coin (ETH, SOL; its currency is the payment currency's chain): its gas and, on Base, its L1 data fee. amountUsd at nativePriceUsd
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
l1FeeTokenAmountOptionalThe part of fee that paid Base's L1 data fee, in the native coin. Absent off Base, and on transactions recorded before it was
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
nativePriceUsdstringOptionalNativePriceUSD is the USD price of the chain's native coin when the transaction was recorded (what its fee cost in USD). Absent when the price wasn't available then
confirmedAtstringOptionalWhen the chain confirmed it: its block's time (settlement.transaction.blockTime). Absent only on records made before it was recorded
paidstringOptionalEverything the customer's wallet sent, in the currency's units (a decimal string): the amount plus the network fee paid on top (settlement.split). A refund's base (refundPercent of it). Only for the merchant; absent when the split wasn't recorded
Only for the resource's owner
paidMinUnitsstringOptionalThe same in the currency's smallest unit, a string of digits. Only for the merchant, like paid
Only for the resource's owner
paidUsdstringOptionalThe same in USD, at the payment's time, a decimal string. Only for the merchant, like paid
Only for the resource's owner
refundRefundSummaryOptionalIts refund (one per transaction); omitted without one. The merchant's own refund appears once its transfer confirmed (approved)
Only for the resource's owner
9 fields of
RefundSummaryuuidstringThe refund (refund@…)
statusstringpending, approved or rejected
One of
pendingapprovedrejectedfailedDeclared, never set: an approval that fails leaves the refund pending, to approve again
initiatedBystringcustomer (a request) or merchant
refundPercentnumberThe share of what the customer paid it sends back, a percent string ("100": all of it). Written as refundPercent
amountstringOptionalWhat it sends back, in the currency's units (a decimal string). Absent when its currency isn't known (a refund requested before refunds named it)
amountMinUnitsstringThe same in the currency's smallest unit (a string of digits)
amountUsdstringOptionalThe same in USD, at the payment's time (a decimal string). Absent when unknown (a refund requested before it was recorded)
createdAtstringWhen it was requested or started
respondedAtstringOptionalWhen it was approved (confirmed) or rejected; absent while pending
refundablebooleanOptionalWhether it can be refunded now
Only for the resource's owner
notRefundableReasonstringOptionalWhy not: refundExists or heldFundsReleased. Omitted when refundable
Only for the resource's owner
checkoutOpenedAtstringOptionalWhen its checkout session was created (the payment's uuid is the session's). Omitted for a payment whose uuid doesn't say (made before UUIDv7s)
Errors
The common codes only, as any route (what each means):
- 400validation_failed
- 401unauthorized
- 403forbidden
- 403policy_disabled
- 404not_found
- 429rate_limit_exceeded
- 500internal
- 504timeout
Get payment#
GET /payments/
Reads one of the caller's payments by its uuid (pay@… or bare), in the request's space (with includeMembers, its members' too), so in its mode too. Another kind of id (sub@…): 404.
- 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/payments/$PAYMENT_UUID" \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a Paymentconst payment = await client. payments. get( paymentUuid); // pay@…, the checkout session's idconsole.log(payment.uuid, payment.reference, payment.amountUsd, 'USD', payment.metadata); // Runs GET /payments?reference= and returns its one payment: a NotFoundError (404,// not_found) until the customer paid.const byReference = await client. payments. getByReference( 'order-1042');console.log(`order-1042 was paid by ${byReference.from}`);payment = client. payments. get( payment_uuid) # pay@…, the id of its checkout sessionprint(payment.reference, payment.amount_usd, "USD", payment.tx_hash, payment.metadata) # Runs GET /payments?reference= and returns its one payment (NotFoundError when none).by_reference = client. payments. get_by_reference( "order-1042") # your order idprint(by_reference.uuid)payment, err := client.Payments.Get(ctx, paymentUUID, nil) // pay@…if err != nil { log.Fatal(err)}fmt.Println(payment.UUID, payment.Reference, payment.AmountUSD, "USD", payment.Metadata) // Runs GET /payments?reference= and returns its one payment.byReference, err := client. Payments. GetByReference( ctx, "order-1042") // your order idif err != nil { log.Fatal(err) // a *qbitflow.NotFoundError (404, not_found) when no payment has this reference}fmt.Println("order-1042 was paid by", byReference.UUID)$payment = $client->payments->get( $paymentUuid); // pay@…echo "{$payment->uuid}: {$payment->amountUsd} USD, tx {$payment->txHash}\n"; // Runs GET /payments?reference= and returns its one payment (a NotFoundException when none).$payment = $client->payments->getByReference( 'order-1042'); // your order idecho "order-1042 was paid by {$payment->uuid}\n";Path parameters
uuidstringRequiredIts prefixed uuid (or the bare uuid)
txuuid
Query parameters
includeMembersbooleanOptionalThe organization's space only (the team, its keys without On-Behalf-Of): a member's too, naming its member (userUuid). Read only: acting on it still switches into the member's space or uses On-Behalf-Of. From a member's space → 400 on includeMembers
Response
A Payment.
33 fields of Payment
uuidstringallow read and create, (generated on creation of the payment link)
A prefixed id (pay@…, sub@…)
createdAtstringfromstringtostringamountstringThe amount in the currency's units, exact, a decimal string ("10" for 10 USDC): amountMinUnits / 10^decimals
amountMinUnitsstringThe amount in the currency's smallest unit, a string of digits ("10000000" for 10 USDC, 6 decimals)
amountUsdstringWhat the customer paid, in USD, a decimal string: the price (and, on a one-time payment, the fees its checkout added: fees), which the contracts split between QBitFlow's fee (the referrer's share included), the organization's fee and the merchant (settlement.split). The network fee a customer pays on top (settlement.split.networkFee) is not in it
currencyIdintegerThe currency paid in, written as the currency object under currency (GET /currencies/:id)
txHashstringHash of the transaction in the blockchain
chainstringOptionalThe chain it was paid on: ETH (Ethereum), BASE (Base) or SOL (Solana), the testnet's for a test-mode transfer (currency.test)
explorerUrlstringOptionalIts transaction on the chain's block explorer (the testnet's in test mode). Omitted without a txHash
testbooleanWhether this is test data (testnets) or live data
userUuidstringOptionalMember the resource belongs to; omitted for the organization's own resources
Only for the resource's owner
referencestringOptionalThe merchant's reference for the payment (an order or invoice id), set when creating its checkout. Only for the merchant: never in the public reads by uuid (GET /hosted/transactions/:txUuid)
Only for the resource's owner
priceUsdstringOptionalPriceUSD is the product's price in USD, as the checkout had it, a decimal string, always present: amountUsd is the price plus the fees' lines. (A payment recorded before checkouts had fees has none stored: its price is its amount, Complete.)
feesarray of FeeLineWhat the checkout added to the price, line by line, as the customer saw them (a tax, shipping, the processing fee when the customer paid it); [] without any
4 fields of each
FeeLinetypestringcustom (the merchant's line) or processingFee (QBitFlow's fee, which the merchant has the customer pay)
One of:
customThe merchant's own line: a tax, shipping, a service feeprocessingFeeQBitFlow's fee, which the merchant has the customer pay (computed by QBitFlow)
labelstringThe line's name, as the checkout shows it ("Processing fee" for the processing fee)
descriptionstringOptionalOptional: more about the line, as the merchant wrote it. Omitted without one
amountUsdstringThe line's amount in USD, a decimal string with at most 2 decimals
productNamestringWhat was paid for: the checkout's product name, as it was when the checkout was created (the product's, or the inline one). Later product edits don't change it
productDescriptionstringOptionalSame, for the product's description; absent without one
metadatamapOptionalMetadata is the merchant's own data, copied from the checkout session that created the payment (its metadata), read-only. {} without any. Only for the merchant
Only for the resource's owner
productUuidstringOptionalThe product paid for; omitted when the payment has none (an inline product)
customerUuidstringOptionalThe customer, when QBitFlow has one (named by the checkout, found by its customerReference, or recorded from the details the customer gave); omitted otherwise
Only for the resource's owner
customerReferencestringOptionalThe merchant's reference of the customer, as the checkout was given it (customerReference), whether or not QBitFlow has a customer with it; omitted otherwise
Only for the resource's owner
notestringOptionalA qbf.cash tipper's message to the handle's owner (only for them); omitted without one
Only for the resource's owner
customerSummaryOptionalThe customer, named (merchant only, API reads): who paid, even once deleted. Omitted without one
Only for the resource's owner
6 fields of
SummaryuuidstringThe customer (GET /customers/:uuid)
firstNamestringFirst name
lastNamestringOptionalLast name, when given
emailstringEmail, lowercase
referencestringOptionalThe merchant's reference of the customer, when it has one
deletedbooleanThe merchant deleted the customer: it still names its rows, but GET /customers/:uuid answers 404
settlementSettlementOptionalHow it settled: its fees, its split and its transaction (only for the merchant)
Only for the resource's owner
5 fields of
SettlementfeePercentnumberQBitFlow's fee on this payment, in bps (1 % = 100 bps), deducted from the amount paid. Written as feePercent, a percent string
organizationFeeOrganizationFeeOptionalThe organization's fee on its member's payment (a marketplace's commission), paid to the organization's wallet. It is taken from what remains after QBitFlow's fee (contracts SPEC §4.1): organization = (amount - QBitFlow's fee) × its rate, and the member receives the rest. While the organization holds the member's funds, it is withheld from what the organization owes them instead of paid on-chain. Absent: none
2 fields of
OrganizationFeeaddressstringOptionalThe organization's wallet that receives the fee (only for the merchant)
Only for the resource's owner
feePercentnumberThe organization's fee, in bps, taken from what remains after the platform fee. Written as feePercent, a percent string
referralFeeReferralFeeOptionalThe referrer's share of QBitFlow's fee. Absent: none
2 fields of
ReferralFeeaddressstringOptionalThe referrer's wallet that receives the fee (only for the merchant)
Only for the resource's owner
feePercentnumberThe referrer's share of the platform fee, in bps (2000 = 20 % of it). Written as feePercent, a percent string
splitSplitOptionalHow the contracts split what the payer paid. For a payment the organization held for its member, the organization's fee was withheld from the member's share (not paid on-chain): the split is the one a direct payment would have had. Absent on records made before the split was recorded
5 fields of
SplitplatformTokenAmountQBitFlow's fee (the referrer's share not included)
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
organizationTokenAmountOptionalThe organization's fee; absent without one
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
referralTokenAmountOptionalThe referrer's share of QBitFlow's fee; absent without one
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
merchantTokenAmountWhat the merchant received (the member, for a member's payment), net of every fee
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
networkFeeTokenAmountOptionalNetworkFee is the network fee the payer paid on top of the amount, in the payment's currency: the gas refund the contracts took in the token (their GasRefundProcessed event), or, for a payment in a chain's native coin, the fee of the transaction the payer's wallet paid (its gas and, on Base, its L1 data fee), bounded by what QBitFlow prepared. Not the transaction's own cost to its sender (transaction.fee). Absent on records made before it was recorded ("0" once recorded as none)
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
transactionSettlementTransactionOptionalThe transaction that paid it. Absent before its confirmation
6 fields of
SettlementTransactionblockNumberstringThe block (Ethereum, Base) or slot (Solana) it landed in, a string of digits
blockTimestringOptionalWhen its block was produced (UTC); when it was recorded if the chain's node didn't give it. Absent only on records made before it was recorded
gasUsedintegerOptionalThe gas it consumed (Ethereum, Base). Absent on Solana
feeTokenAmountWhat the transaction cost its sender, in the chain's native coin (ETH, SOL; its currency is the payment currency's chain): its gas and, on Base, its L1 data fee. amountUsd at nativePriceUsd
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
l1FeeTokenAmountOptionalThe part of fee that paid Base's L1 data fee, in the native coin. Absent off Base, and on transactions recorded before it was
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
nativePriceUsdstringOptionalNativePriceUSD is the USD price of the chain's native coin when the transaction was recorded (what its fee cost in USD). Absent when the price wasn't available then
confirmedAtstringOptionalWhen the chain confirmed it: its block's time (settlement.transaction.blockTime). Absent only on records made before it was recorded
paidstringOptionalEverything the customer's wallet sent, in the currency's units (a decimal string): the amount plus the network fee paid on top (settlement.split). A refund's base (refundPercent of it). Only for the merchant; absent when the split wasn't recorded
Only for the resource's owner
paidMinUnitsstringOptionalThe same in the currency's smallest unit, a string of digits. Only for the merchant, like paid
Only for the resource's owner
paidUsdstringOptionalThe same in USD, at the payment's time, a decimal string. Only for the merchant, like paid
Only for the resource's owner
refundRefundSummaryOptionalIts refund (one per transaction); omitted without one. The merchant's own refund appears once its transfer confirmed (approved)
Only for the resource's owner
9 fields of
RefundSummaryuuidstringThe refund (refund@…)
statusstringpending, approved or rejected
One of
pendingapprovedrejectedfailedDeclared, never set: an approval that fails leaves the refund pending, to approve again
initiatedBystringcustomer (a request) or merchant
refundPercentnumberThe share of what the customer paid it sends back, a percent string ("100": all of it). Written as refundPercent
amountstringOptionalWhat it sends back, in the currency's units (a decimal string). Absent when its currency isn't known (a refund requested before refunds named it)
amountMinUnitsstringThe same in the currency's smallest unit (a string of digits)
amountUsdstringOptionalThe same in USD, at the payment's time (a decimal string). Absent when unknown (a refund requested before it was recorded)
createdAtstringWhen it was requested or started
respondedAtstringOptionalWhen it was approved (confirmed) or rejected; absent while pending
refundablebooleanOptionalWhether it can be refunded now
Only for the resource's owner
notRefundableReasonstringOptionalWhy not: refundExists or heldFundsReleased. Omitted when refundable
Only for the resource's owner
checkoutOpenedAtstringOptionalWhen its checkout session was created (the payment's uuid is the session's). Omitted for a payment whose uuid doesn't say (made before UUIDv7s)
Errors
The common codes only, as any route (what each means):
- 400validation_failed
- 401unauthorized
- 403forbidden
- 403policy_disabled
- 404not_found
- 429rate_limit_exceeded
- 500internal
- 504timeout
List transactions#
GET /transactions
Lists the one-time payments and the subscription bills of the request's space together (with includeMembers, of the organization and its members; with userUuid, of one member), newest first (createdAt, then uuid).
- 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/transactions \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Transaction ({ items, hasMore, nextCursor? })// One feed of one-time payments and subscription bills, newest first; each row reads like its// resource. `type` filters it to one kind (TransactionKind.Payment or TransactionKind.Bill).const feed = await client.transactions.list({ limit: 20 });for (const tx of feed.items) { console.log(tx.type, tx.uuid, tx.amountUsd, 'USD');}# One feed of one-time payments and subscription bills, newest first; each row reads like# its resource. type= filters it to one kind (TransactionKind.PAYMENT or .BILL).feed = client. transactions. list( limit=20)for tx in feed.items: print(tx.type, tx.uuid, tx.amount_usd, "USD")// One feed of one-time payments and subscription bills, newest first; each row reads like// its resource. Type filters it to one kind (TransactionKindPayment or TransactionKindBill).feed, err := client.Transactions.List(ctx, &qbitflow. TransactionListParams{Limit: 20})if err != nil { log.Fatal(err)}for _, tx := range feed.Items { fmt.Println(tx.Type, tx.UUID, tx.AmountUSD, "USD")}// One feed of one-time payments and subscription bills, newest first; each row reads like its// resource. `type` filters it to one kind (TransactionKind::PAYMENT or TransactionKind::BILL).$feed = $client->transactions->list(new \QBitFlow\Params\TransactionListParams( limit: 20));foreach ($feed->items as $transaction) { echo "{$transaction->type} {$transaction->uuid} {$transaction->amountUsd} USD\n";}Query parameters
limitintegerOptionalPage size: 20 when absent or ≤ 0, at most 100 (a larger one is clamped, not refused)
cursorstringOptionalThe previous page's nextCursor, verbatim; omit for the first page
max=200customerUuidstringOptionalOnly this customer's
productUuidstringOptionalOnly this product's
createdAfterstringOptionalOnly those created after this instant, excluded (RFC 3339, e.g. 2026-10-04T12:00:00Z, or a date: its midnight UTC)
createdBeforestringOptionalOnly those created before this instant, excluded (RFC 3339 or a date, as createdAfter)
includeMembersbooleanOptionalThe organization's space only (the team, its keys without On-Behalf-Of): its members' too, each naming its member (userUuid). From a member's space → 400 on includeMembers
userUuidstringOptionalThe organization's space only (owners and admins): this member's only, read from the organization's space (a removed member's too). Not with includeMembers (400 on userUuid)
typestringOptionalOnly the one-time payments (payment) or only the subscriptions' bills (bill)
oneof=payment billOne of:
paymentA one-time payment (pay@…): GET /payments/:uuidbillA subscription's bill (sub-hist@…): GET /bills/:uuid
subscriptionUuidstringOptionalOnly this subscription's bills (its sub@ uuid, or the bare uuid)
txuuidrefundedbooleanOptionalOnly the rows with (true) or without (false) an approved refund
Response
A page: { "items": Transaction[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.
36 fields of each Transaction
typestringpayment or bill
One of:
paymentA one-time payment (pay@…): GET /payments/:uuidbillA subscription's bill (sub-hist@…): GET /bills/:uuid
uuidstringThe payment's (pay@…) or the bill's (sub-hist@…) prefixed uuid
A prefixed id (pay@…, sub@…)
createdAtstringWhen it was recorded, once confirmed on-chain
fromstringThe customer's wallet that paid
tostringThe wallet that received it (the merchant's, or the organization's while it holds the member's funds)
productNamestringWhat was paid for: a payment keeps its checkout's product name (the product's when the checkout was created, or the inline one), a bill its subscription's product name when it was billed. Later product edits don't change it
productDescriptionstringOptionalSame, for the description; absent without one
priceUsdstringOptionalThe price in USD, a decimal string: a payment's checkout price, a bill's subscription's locked price. amountUsd is the price plus the fees' lines. Absent on a bill of a subscription without a locked price
feesarray of FeeLineWhat was added to the price, line by line: a payment's checkout lines, a bill's subscription's (locked with its price); [] without any
4 fields of each
FeeLinetypestringcustom (the merchant's line) or processingFee (QBitFlow's fee, which the merchant has the customer pay)
One of:
customThe merchant's own line: a tax, shipping, a service feeprocessingFeeQBitFlow's fee, which the merchant has the customer pay (computed by QBitFlow)
labelstringThe line's name, as the checkout shows it ("Processing fee" for the processing fee)
descriptionstringOptionalOptional: more about the line, as the merchant wrote it. Omitted without one
amountUsdstringThe line's amount in USD, a decimal string with at most 2 decimals
amountstringWhat the customer paid, in the currency's units, exact (a decimal string), as on the Payment or the Bill
amountMinUnitsstringThe same in the currency's smallest unit, a string of digits
amountUsdstringWhat the customer paid, in USD, a decimal string: the price and the fees' lines (the network fee paid on top is settlement.split.networkFee)
currencyIdintegerThe currency paid in, written as the currency object under currency
productUuidstringOptionalThe product paid for; absent when there is none (an inline product)
txHashstringThe transaction that paid it
customerUuidstringOptionalThe customer, when QBitFlow has one; absent otherwise
Only for the resource's owner
customerSummaryOptionalThe customer, named (merchant only, API reads): who paid, even once deleted. Absent without one
Only for the resource's owner
6 fields of
SummaryuuidstringThe customer (GET /customers/:uuid)
firstNamestringFirst name
lastNamestringOptionalLast name, when given
emailstringEmail, lowercase
referencestringOptionalThe merchant's reference of the customer, when it has one
deletedbooleanThe merchant deleted the customer: it still names its rows, but GET /customers/:uuid answers 404
customerReferencestringOptionalThe merchant's reference of the customer, as the checkout was given it; absent otherwise
Only for the resource's owner
subscriptionUuidstringOptionalA bill's subscription (sub@…); absent on a payment
periodStartstringOptionalA bill's period's start (its due date); absent on a payment, and on bills recorded before periods were
periodEndstringOptionalA bill's period's end: paid until then; absent on a payment, and on bills recorded before periods were
referencestringOptionalA payment's own reference (a bill has none of its own). Only for the merchant
Only for the resource's owner
subscriptionReferencestringOptionalThe reference of a bill's subscription, as in the subscription webhooks
metadatamapOptionalMetadata is a payment's merchant data (copied from its checkout session); {} for a bill (a bill carries none: its subscription's is on the subscription). Only for the merchant
Only for the resource's owner
chainstringOptionalThe chain it was paid on: ETH (Ethereum), BASE (Base) or SOL (Solana), the testnet's for a test-mode transfer (currency.test)
explorerUrlstringOptionalIts transaction on the chain's block explorer (the testnet's in test mode). Omitted without a txHash
testbooleanWhether this is test data (testnets) or live data
userUuidstringOptionalMember the resource belongs to; omitted for the organization's own resources
Only for the resource's owner
settlementSettlementOptionalIts fees, split and transaction, as on the Payment or the Bill (only for the merchant)
Only for the resource's owner
5 fields of
SettlementfeePercentnumberQBitFlow's fee on this payment, in bps (1 % = 100 bps), deducted from the amount paid. Written as feePercent, a percent string
organizationFeeOrganizationFeeOptionalThe organization's fee on its member's payment (a marketplace's commission), paid to the organization's wallet. It is taken from what remains after QBitFlow's fee (contracts SPEC §4.1): organization = (amount - QBitFlow's fee) × its rate, and the member receives the rest. While the organization holds the member's funds, it is withheld from what the organization owes them instead of paid on-chain. Absent: none
2 fields of
OrganizationFeeaddressstringOptionalThe organization's wallet that receives the fee (only for the merchant)
Only for the resource's owner
feePercentnumberThe organization's fee, in bps, taken from what remains after the platform fee. Written as feePercent, a percent string
referralFeeReferralFeeOptionalThe referrer's share of QBitFlow's fee. Absent: none
2 fields of
ReferralFeeaddressstringOptionalThe referrer's wallet that receives the fee (only for the merchant)
Only for the resource's owner
feePercentnumberThe referrer's share of the platform fee, in bps (2000 = 20 % of it). Written as feePercent, a percent string
splitSplitOptionalHow the contracts split what the payer paid. For a payment the organization held for its member, the organization's fee was withheld from the member's share (not paid on-chain): the split is the one a direct payment would have had. Absent on records made before the split was recorded
5 fields of
SplitplatformTokenAmountQBitFlow's fee (the referrer's share not included)
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
organizationTokenAmountOptionalThe organization's fee; absent without one
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
referralTokenAmountOptionalThe referrer's share of QBitFlow's fee; absent without one
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
merchantTokenAmountWhat the merchant received (the member, for a member's payment), net of every fee
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
networkFeeTokenAmountOptionalNetworkFee is the network fee the payer paid on top of the amount, in the payment's currency: the gas refund the contracts took in the token (their GasRefundProcessed event), or, for a payment in a chain's native coin, the fee of the transaction the payer's wallet paid (its gas and, on Base, its L1 data fee), bounded by what QBitFlow prepared. Not the transaction's own cost to its sender (transaction.fee). Absent on records made before it was recorded ("0" once recorded as none)
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
transactionSettlementTransactionOptionalThe transaction that paid it. Absent before its confirmation
6 fields of
SettlementTransactionblockNumberstringThe block (Ethereum, Base) or slot (Solana) it landed in, a string of digits
blockTimestringOptionalWhen its block was produced (UTC); when it was recorded if the chain's node didn't give it. Absent only on records made before it was recorded
gasUsedintegerOptionalThe gas it consumed (Ethereum, Base). Absent on Solana
feeTokenAmountWhat the transaction cost its sender, in the chain's native coin (ETH, SOL; its currency is the payment currency's chain): its gas and, on Base, its L1 data fee. amountUsd at nativePriceUsd
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
l1FeeTokenAmountOptionalThe part of fee that paid Base's L1 data fee, in the native coin. Absent off Base, and on transactions recorded before it was
3 fields of
TokenAmountamountstringIn the token's units, exact: amountMinUnits / 10^decimals, a decimal string ("12.5")
amountMinUnitsstringThe on-chain integer, in the token's smallest unit, a string of digits ("12500000")
amountUsdstringOptionalIts value in USD, a decimal string; absent when no price was known
nativePriceUsdstringOptionalNativePriceUSD is the USD price of the chain's native coin when the transaction was recorded (what its fee cost in USD). Absent when the price wasn't available then
confirmedAtstringOptionalWhen the chain confirmed it: its block's time (settlement.transaction.blockTime). Absent only on records made before it was recorded
paidstringOptionalEverything the customer's wallet sent, in the currency's units (a decimal string): the amount plus the network fee paid on top (settlement.split). A refund's base (refundPercent of it). Only for the merchant; absent when the split wasn't recorded
Only for the resource's owner
paidMinUnitsstringOptionalThe same in the currency's smallest unit, a string of digits. Only for the merchant, like paid
Only for the resource's owner
paidUsdstringOptionalThe same in USD, at the payment's time, a decimal string. Only for the merchant, like paid
Only for the resource's owner
refundRefundSummaryOptionalIts refund (one per transaction); omitted without one. The merchant's own refund appears once its transfer confirmed (approved)
Only for the resource's owner
9 fields of
RefundSummaryuuidstringThe refund (refund@…)
statusstringpending, approved or rejected
One of
pendingapprovedrejectedfailedDeclared, never set: an approval that fails leaves the refund pending, to approve again
initiatedBystringcustomer (a request) or merchant
refundPercentnumberThe share of what the customer paid it sends back, a percent string ("100": all of it). Written as refundPercent
amountstringOptionalWhat it sends back, in the currency's units (a decimal string). Absent when its currency isn't known (a refund requested before refunds named it)
amountMinUnitsstringThe same in the currency's smallest unit (a string of digits)
amountUsdstringOptionalThe same in USD, at the payment's time (a decimal string). Absent when unknown (a refund requested before it was recorded)
createdAtstringWhen it was requested or started
respondedAtstringOptionalWhen it was approved (confirmed) or rejected; absent while pending
refundablebooleanOptionalWhether it can be refunded now
Only for the resource's owner
notRefundableReasonstringOptionalWhy not: refundExists or heldFundsReleased. Omitted when refundable
Only for the resource's owner
Errors
The common codes only, as any route (what each means):
- 400validation_failed
- 401unauthorized
- 403forbidden
- 403policy_disabled
- 404not_found
- 429rate_limit_exceeded
- 500internal
- 504timeout
List payment failures#
GET /payment-failures
Lists the failed payment attempts of the request's space (with includeMembers, of the organization and its members; with userUuid, of one member), newest first: one-time payments, subscription checkouts and bills the customer tried to pay and couldn't, and why. A failure is never money: none is ever in the payments, the export or the volume.
- 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/payment-failures \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Failure ({ items, hasMore, nextCursor? })Query parameters
limitintegerOptionalPage size: 20 when absent or ≤ 0, at most 100 (a larger one is clamped, not refused)
cursorstringOptionalThe previous page's nextCursor, verbatim; omit for the first page
max=200customerUuidstringOptionalOnly this customer's
productUuidstringOptionalOnly this product's
createdAfterstringOptionalOnly those created after this instant, excluded (RFC 3339, e.g. 2026-10-04T12:00:00Z, or a date: its midnight UTC)
createdBeforestringOptionalOnly those created before this instant, excluded (RFC 3339 or a date, as createdAfter)
includeMembersbooleanOptionalThe organization's space only (the team, its keys without On-Behalf-Of): its members' too, each naming its member (userUuid). From a member's space → 400 on includeMembers
userUuidstringOptionalThe organization's space only (owners and admins): this member's only, read from the organization's space (a removed member's too). Not with includeMembers (400 on userUuid)
kindstringOptionalOnly one kind: payment, subscriptionCheckout or bill
oneof=payment subscriptionCheckout billOne of:
paymentA one-time payment's attempt (its checkout: pay@…)subscriptionCheckoutA subscription checkout's: its creation and first bill (sub@…)billA subscription's bill (sub-hist@…)
categorystringOptionaloneof=insufficientBalance allowanceExhausted approvalRevoked maxAmountExceeded reverted notConfirmed signatureRejected otherOne of
otherinsufficientBalanceThe customer's wallet couldn't pay (the token, or the gas of a payment they send)allowanceExhaustedA subscription's allowance is used up or expiredapprovalRevokedThe customer's wallet no longer lets the subscription pull the tokenmaxAmountExceededA bill above the customer's maximum per periodrevertedSent and reverted on-chain (the wallet changed between the check and the block)notConfirmedSent, never taken or confirmed in timesignatureRejectedThe customer's signature was refused (expired, invalid)
subscriptionUuidstringOptionalOnly this subscription's bills (sub@…)
txuuid
Response
A page: { "items": Failure[], "hasMore": …, "nextCursor"?: … }. Pass nextCursor back as cursor for the next page; it is absent when hasMore is false.
20 fields of each Failure
uuidstringThe failure's own id, a plain uuid (a failed attempt isn't a transaction: it has no prefix)
kindstringpayment, subscriptionCheckout or bill
One of:
paymentA one-time payment's attempt (its checkout: pay@…)subscriptionCheckoutA subscription checkout's: its creation and first bill (sub@…)billA subscription's bill (sub-hist@…)
txUuidstringWhat failed: the checkout (pay@…, sub@…: the id its payment or subscription would have had) or the bill (sub-hist@…: its id once paid)
attemptintegerIts number among its transaction's failed attempts, from 1
subscriptionUuidstringOptionalA bill's subscription (sub@…)
codestringThe error code (errors), e.g. insufficient_funds
categorystringWhat it means, from the code: insufficientBalance, allowanceExhausted, approvalRevoked, maxAmountExceeded, reverted, notConfirmed, signatureRejected or other
One of
otherinsufficientBalanceThe customer's wallet couldn't pay (the token, or the gas of a payment they send)allowanceExhaustedA subscription's allowance is used up or expiredapprovalRevokedThe customer's wallet no longer lets the subscription pull the tokenmaxAmountExceededA bill above the customer's maximum per periodrevertedSent and reverted on-chain (the wallet changed between the check and the block)notConfirmedSent, never taken or confirmed in timesignatureRejectedThe customer's signature was refused (expired, invalid)
messagestringOptionalWhat the customer was told; absent without a message
attemptedstringWhat the customer tried to pay, in the currency's units, exact (a decimal string): never received
attemptedMinUnitsstringThe same in the currency's smallest unit, a string of digits
attemptedUsdstringThe same in USD, a decimal string
currencyIdintegerThe currency it was tried in, written as the currency object under currency
fromstringThe customer's wallet
txHashstringOptionalThe transaction, when one was sent (a revert, a timeout)
customerUuidstringOptionalThe customer, when QBitFlow has one
Only for the resource's owner
productUuidstringOptionalThe product, when it had one
createdAtstringWhen it failed
customerSummaryOptionalThe customer, named (API reads)
Only for the resource's owner
6 fields of
SummaryuuidstringThe customer (GET /customers/:uuid)
firstNamestringFirst name
lastNamestringOptionalLast name, when given
emailstringEmail, lowercase
referencestringOptionalThe merchant's reference of the customer, when it has one
deletedbooleanThe merchant deleted the customer: it still names its rows, but GET /customers/:uuid answers 404
testbooleanWhether this is test data (testnets) or live data
userUuidstringOptionalMember the resource belongs to; omitted for the organization's own resources
Only for the resource's owner
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: The customer's receipt · Authentication & roles · Spaces · Reads · Response fields · Who paid (customer) · Refund state (refund, refundable) · When (confirmedAt, checkoutOpenedAt) · What the amounts mean · Failed payment attempts (GET /).
Read all 10
The customer's receipt
- Once a payment is recorded, its customer is emailed its receipt, once: what was charged, the network fee on its own row, the total that left their wallet, the network, their wallet and the transaction on the explorer, all from the recorded split (
settlement.split). Sent in the merchant's name; the settingemails.customerReceiptsturns it off (on by default). Never in test mode, nor without a customer with an email. A receipt that can't be sent never affects the payment.
Authentication & roles
The v1 / beta paths are gone (/transaction/payments, /transaction/payments/combined, /transaction/payment/:uuid, /transaction/payment/reference/:reference, /transaction/failures, /transaction/info/:txUuid, /transaction/status[/ws], /transaction/payment[/intent], /transaction/payment/run-test-tx): 404.
POST /hosted/payments/intent(and the subscription intent, Hosted subscriptions) takescustomerInformationwhen the session has no customer: what itscustomerDetailsasks is required:email→customerInformation.email;full→ also the first name andlastName(400validation_failedoncustomerInformationor the missing field); a session asking nothing (nocustomerDetails) → optional, and ignored (nothing is kept). The intent writes no customer: the details are kept with the session, and the customer is recorded with the payment (a subscription: with it; a free trial: when it starts), so an intent never paid adds none. The space's unverified customer with the same email, whatever its casing, is reused; a customer the merchant created (verified) never is, whatever its email: the payer's email then becomes an unverified customer of its own (a deleted customer is never reused either; Customers § Verified customers).customerInformationhas noreference(the merchant's own id is never the customer's to give). Ignored when the merchant named the customer (customerUuid, or its owncustomerReference: the checkout then asks nothing, Checkout sessions § The customer).- A payer who can't pay is told at the intent (payment, subscription): a wallet that doesn't hold the amount (with a 5 % margin for the price and the network fee) →
422insufficient_funds(a token),422insufficient_native_funds(the chain's own coin), the codes the network's own refusal gives (errors). Nothing is prepared; top the wallet up and make the intent again. Asignerthat isn't an address of the currency's chain →400validation_failedonsigner. - The paying wallet can't be the receiving one: a
signerthat is the merchant's receiving wallet (or the organization's, while it holds the member's funds) →400sender_is_receiver, nothing prepared. - A currency the checkout doesn't take: one of the catalog the session never offered, or one its merchant (or the organization) removed since it opened →
409currency_not_accepted,details.currency(its code): pick another of the hosted session'savailableCurrencies. Acurrencythat isn't a code of the session's mode →400validation_failedoncurrency. - Amounts fit the chain (an intent: payment, subscription, allowance): the price converted to the chosen token's smallest unit must fit what the chain holds,
u64on Solana,uint160for an EVM token (Permit2),uint256for an EVM chain's coin, and be at least one unit. Too large or below one unit →400validation_failedoncurrency(another token may hold it); a subscription's allowance (a period's amount ×numPeriods, with its buffer and network fees) too large →400validation_failedonnumPeriods. Never truncated. - The intent's and the send's
uuidis the checkout session'spay@id, or its bare uuid.
Spaces
- Every payment belongs to one space (spaces): the organization's or a member's, in one mode. Every route works in the request's space: the team (and organization keys) sees the organization's payments, a member (and their keys) their own, and an organization key with
On-Behalf-Of: <userUuid>(or the dashboard switched into the member's space) the member's. - A payment of another space, of another organization or of the other mode is never listed, and answers
404by uuid: existence is never revealed. Another organization's payment uuid answers like an unknown one. - Organization-wide lists (
?includeMembers=trueon both lists): the organization's space (the team's sessions, the organization's keys withoutOn-Behalf-Of) lists its members' payments and bills too, in its mode only, each naming its member (userUuid; the organization's own have none). Every member's space of the mode is read, removed members' included (their data stays the organization's, Members and held funds § Remove), and so is the personal space an admin kept from before their promotion. From a member's space (a member's session or key,On-Behalf-Of, the dashboard switched into a member) →400validation_failedonincludeMembers. Without it a list is the request's space only. A webhook'suserUuidis the member to name inOn-Behalf-Offor follow-up reads of that member's resources. - One member's rows (
?userUuid=<member>on both lists and the failures log): from the organization's space, owners and admins (and the organization's keys, capped at admin) read that member's rows only, without switching into their space orOn-Behalf-Of: the marketplace dashboard's drill-down. A member removed from the mode still reads; a user who isn't a member in this mode →404; from a member's space →400validation_failedonuserUuid; withincludeMembers→400onuserUuid. - Organization-wide reads by uuid:
GET /payments/:uuid?includeMembers=true(andGET /bills/:uuid,GET /subscriptions/:uuid, Subscriptions and bills) read a member's row from the organization's space, in its mode, with itsuserUuid: the row a list withincludeMembersshowed. Same rules as the lists (a member's space →400onincludeMembers; another organization's or the other mode's →404). Read only: refunding it still switches into the member's space (or usesOn-Behalf-Of).
Reads
GET /payments/:uuidreturns one of the space's payments, by itspay@-prefixed uuid (the value emitted as the payment'suuid, its checkout session's) or its bare uuid. Unknown uuid, another kind of id (sub@…: it isn't a payment), another space's or mode's →404; malformed →400validation_failedonuuid.- By reference:
GET /payments?reference=<reference>(it wasGET /transaction/payment/reference/:reference): the list filtered on the merchant's reference, an envelope of 0 or 1 item (items: []when no payment has it; never404). References are unique per space, so withincludeMembers(oruserUuid) it may list one per space read.referencefollows thereferencevalidator (max=100): anything else →400validation_failedonreference. GET /paymentsandGET /transactionsare cursor-paginated (pagination): the envelope{ items, hasMore, nextCursor? },nextCursorpresent only whenhasMore;?limit=(20 by default, at most 100: larger is clamped) and?cursor=(the previous page'snextCursor, verbatim: anything else →400validation_failedoncursor).- Order: newest first, by
createdAt(when the payment or the bill was recorded) thenuuid, both descending. Rows recorded at the same instant are told apart by their uuid, so a walk visits every row exactly once, whatever the page size. - Filters (both lists, each optional, combined with AND):
customerUuid,productUuid,createdAfter,createdBefore(RFC 3339 instants or dates, both excluded; pagination),includeMembers,userUuid(above),refunded(true: only the rows with an approved refund, what a "Refunded" badge means;false: the others, a pending or rejected refund included).GET /paymentsalso takesreference(above).GET /transactionsalso takestype(paymentorbill: one kind of row; it wassource, withsubscriptionHistory) andsubscriptionUuid(sub@…or a bare uuid: that subscription's bills only, so no payment row; another space's subscription gives an empty list). A malformed value →400validation_failedon its name (type: one of the two values). - The transactions feed (
GET /transactions, it wasGET /transaction/payments/combined) merges one-time payments and subscription bills intoTransactionrows, each with itstype(paymentorbill; it wassource). A row reads like its resource (PaymentorBill):amount/amountMinUnits/amountUsd,currency,priceUsdandfees(a bill's are its subscription's locked price and lines, what each bill charges;priceUsdabsent on a bill of a subscription without a locked price),productName,productDescription,settlement,confirmedAt,paid/paidMinUnits/paidUsd,refund/refundable,customer,metadata(a payment's;{}on a bill: its subscription's is on the subscription), and for a bill itssubscriptionUuid,subscriptionReference,periodStartandperiodEnd. - References: a payment row carries its own
reference(when it has one). A bill has none of its own (billing runs automatically), so it carriessubscriptionReference, its subscription's reference, as the subscription webhooks do. Each is absent when empty.reference,customerUuid,metadataandsettlementare the merchant's (whenAuth), as onPayment.
Response fields
- A payment's
uuidis written with itspay@prefix (a bill'ssub-hist@). - Absent means no value (naming):
reference,customerUuid,customerReference,productUuid,productDescription,note,refund,confirmedAt(only on records made before it was recorded: § When),paid*,userUuid(the organization's own) are absent when they have none (nevernullor"").feesis always present ([]without any),metadatatoo ({}). userUuid,customerUuid,customerReference,reference,note,customer,metadata,settlement,paid*and the refund state are the merchant's (resource:"whenAuth"): present on the authenticated reads, never on the hosted pages' public reads. A payment names no organization.productUuidnames the product paid for; absent when the payment has none (an inline product).- The currency is the
currencyobject (Currencies:id,code,symbol,name,chain,decimals,address,mainCurrencyId,test) onPaymentandTransactionrows; thecurrencyIdkey is gone. - Where to check it:
chain(ETH,BASEorSOL: the chain it was paid on; a test-mode payment's is that chain's testnet,test: true) andexplorerUrl(its transaction on the chain's block explorer: Etherscan, Basescan, Solscan, their testnets' in test mode) onPayment, bills,Transactionrows, refunds, and inpayment.completedandsubscription.billed. Link toexplorerUrlrather than building explorer links: QBitFlow may change explorers. - Merchant metadata (
metadata): the checkout session's metadata, copied once when the payment is recorded (Checkout sessions § Metadata). Read-only on the payment (no route changes it);{}when the checkout had none (a product link's visit, a tip).payment.completedcarries it. Never on the hosted pages. - The settlement (
settlement, the merchant's; it wasmetadata): how the payment settled:feePercent(QBitFlow's fee, a percent string),organizationFee/referralFee(feePercent,address; absent without one),split(below) andtransaction(blockNumber,blockTime,gasUsed,feeand Base'sl1Feein the chain's native coin,nativePriceUsd; absent before the confirmation).referralFeenever shows its referral's id nor its terms (until when the referrer earns its share).
Who paid (customer)
- Every payment, bill and transactions row (and subscription, refund) names its customer (merchant only, API reads):
customer: { uuid, firstName, lastName?, email, reference?, deleted }, read with the row, one lookup per page. Absent when the row has no customer. Webhooks keepcustomerUuidonly. - A deleted customer still names its rows, with
deleted: true(whileGET /customers/:uuidanswers404). - A customer is always read in its row's own space: a row never names another space's customer.
- A transactions row also carries
customerReference, asPaymentdoes.
Refund state (refund, refundable)
On Payment, bills and Transaction rows (merchant only, API reads):
refund: the transaction's refund, if any (uuid,status,initiatedBy,refundPercent,amount,amountMinUnits,amountUsd,createdAt,respondedAt: theRefundfields of the same names, Refunds). One refund per transaction, whatever it became: a payment is never refunded twice (a partial refund isn't followed by another). Itsuuidandstatusare what a "refunded" badge needs (no flatrefundUuid/refundStatuskeys: one name per concept).refundable: whether a refund would be accepted now (the customer's request, the merchant'sPOST /refunds/intent).falsewithnotRefundableReason:heldFundsReleased: held for a member and released to them since (checked first);refundExists: it has its refund (a customer's request, pending or answered, or a merchant's refund sent and confirmed). A merchant's refund prepared or being confirmed isn't recorded yet:refundablestaystrueuntil it confirms (its intent then answers409refund_already_exists).
paid/paidMinUnits/paidUsd: everything the customer paid, the refund's base (Refunds § What a refund pays back), from the recorded split. Absent when the split wasn't recorded.
When (confirmedAt, checkoutOpenedAt)
confirmedAt(payments and bills alike): when the chain confirmed it, its block's time (settlement.transaction.blockTime, the same instant). When the chain's node doesn't give the block's time, both are the time QBitFlow recorded the confirmation (to the second), so every payment and bill recorded with itssettlement.transactionhas one; it is absent only on records made before QBitFlow recorded it (and thensettlement.transaction.blockTimeis absent too).createdAtis when QBitFlow recorded the payment, moments after its block.checkoutOpenedAt(payments): when its checkout session was created (the payment's uuid is the session's).
What the amounts mean
- USD amounts are decimal strings (naming):
amountUsd,priceUsd,paidUsd, a fee line'samountUsd, every…Usd: the exact value, canonical ("12.5","1000","0"), never a JSON number. Computed values (a split part, a network fee) have at most 6 decimals. - Token amounts come in pairs:
amount(in the currency's units, exact:"12.5") andamountMinUnits(the on-chain integer:"12500000"), withamountUsdnext to them.amountchanged meaning: it was the USD amount (a number); it is now the token amount, and the USD value isamountUsd. amountUsdis what the customer paid, in USD (the price, at the checkout, plus a payment'sfees), onPayment, bills andTransactionrows alike;amount/amountMinUnitsthe same in the currency. It is what the contracts split.- A payment's
priceUsdis its product's price at the checkout (it wasprice, a number), andfeeswhat its checkout added (Checkout sessions § Fees: the merchant's lines and the processing fee the customer paid,{type, label, description?, amountUsd},[]without any):amountUsd = priceUsd + Σ fees.amountUsd. On payments recorded before fees existed,priceUsdisamountUsdandfeesis[]. QBitFlow's fee is taken on the amount; with a processing fee, the merchant's share (settlement.split.merchant, plusorganizationon a member's payment) is at least the price and the other lines. settlement.splitis how the contracts split it, each part a token amount{ amount, amountMinUnits, amountUsd }:platform(QBitFlow's fee),referral(the referrer's share of QBitFlow's fee, apart fromplatform),organization(the organization's fee on a member's payment) andmerchant(what the merchant's wallet received, or what the organization owes a member whose funds it holds);organizationandreferralare absent when none.platform + referral + organization + merchant = amount, exactly, in each unit (the USD parts are rounded to 6 decimals, the merchant's computed last so they add up toamountUsd). QBitFlow's fee as the accounting export counts it (platformFee) isplatform + referral.settlement.split.networkFeeis the network fee the customer paid on top of the amount, in the token (absent on payments recorded before it was;"0"when none): not part of the amount, nor of the split. Everything the customer's wallet sent ispaid(amount + networkFee): a refund's base (Refunds).settlement.transaction.feeis something else: what the transaction cost its sender, in the chain's native coin.- Show the split as recorded: never recompute it from the rates (
settlement.feePercent,settlement.organizationFee.feePercent), which round per step. productNameandproductDescription(they werenameanddescription) are a copy of what was paid for: a payment keeps its checkout's product (the product's name and description when the checkout was created, or its inline ones), a bill its subscription's product when it was billed (the first bill: the checkout's). Editing or deleting the product later never changes them.
Failed payment attempts (GET /payment-failures)
The failures log (it was GET /transaction/failures): every attempt a customer made to pay and couldn't, for the dashboard (why customers fail, and what it costs). A failure is never money: never a payment or a bill, never in the payment lists, the accounting export, the ledger or the metrics' volume (metrics.md counts them apart, under failures). No webhook announces one.
- What is logged: an attempt the payer signed and sent, or that was refused at send:
kind: payment: a one-time payment's attempt;txUuidispay@…, the uuid its payment has once paid;kind: subscriptionCheckout: a subscription checkout's (its first bill, or a trial's start);txUuidissub@…, the subscription's uuid once created;kind: bill: every failed bill (sub-hist@…, the bill's uuid once paid), with itssubscriptionUuid, the notice of a bill waiting for a new maximum included (category: maxAmountExceeded).
Never an intent refused (a wallet that can't pay is refused at the intent, before anything is signed), never a checkout left to expire, never a bill of a paused or stopped subscription (not billed: nothing failed).
- A failure's own
uuidis a plain uuid (no prefix): a failed attempt isn't a transaction. - Once per attempt: an attempt recorded again (a retried step) is still one row.
attemptnumbers a transaction's failed attempts from 1; a bill's is its dunning's attempt, and the notice of a new maximum spends none (it carries the last attempt's number). codeis the error code the payer got (errors),messagewhat they were told (absent when nothing was),createdAtwhen it failed.categoryis what the code means, one table for every kind:
| category | Codes | |------------|-------| | insufficientBalance | insufficient_funds, insufficient_native_funds | | allowanceExhausted | insufficient_allowance, allowance_expired, allowance_too_low | | approvalRevoked | token_not_approved | | maxAmountExceeded | max_amount_exceeded | | reverted | tx_failed | | notConfirmed | tx_not_sent (and tx_not_confirmed, no longer sent: only on failures recorded before, errors) | | signatureRejected | invalid_signature, signature_expired | | other | any other code |
A new code may join a category (or other); a new category is a new enum value (clients with exhaustive switches must handle it).
- What the customer tried to pay, never received:
attempted(in the currency's units),attemptedMinUnits(its smallest unit) andattemptedUsd(a decimal string; it was a number), incurrency(the currency object; it wascurrencyId).from: the customer's wallet.txHash: the transaction, when one of this payment was sent (a revert, a timeout); absent otherwise (refused at send, or the hash a payer sent was another transaction's).productUuidwhen it had a product.customerUuidandcustomer(as on payments, § Who paid) when QBitFlow knows the customer: a bill's always, a checkout's when the merchant named the customer (a new payer's details are only recorded with their payment). - Order and pages: newest first, by
createdAtthenuuid; the list envelope (pagination),limit20 by default, at most 100. - Filters (each optional, combined with AND):
kind,category(a value not listed →400validation_failedon its name),subscriptionUuid(sub@…or a bare uuid: that subscription's bills), and the list filterscustomerUuid,productUuid,createdAfter,createdBefore,includeMembers,userUuid(as the payment lists: § Reads, § Spaces; each member's row names itsuserUuid). - Spaces: the request's space, each mode its own; another organization's attempts are never listed.
- Kept 25 months (the dashboard's window, and the month before), then deleted.
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) - 400invalid_
signature POST /: the signature doesn't match, or is older than 5 minutes; a send route: the transaction isn't the payer's signature over what the intent prepared (Payments and transactions § Sending a signed transaction)webhooks/ verify - 400sender_
is_ receiver a transfer whose paying wallet is the wallet it pays (a payment, a subscription, a refund, a release)
- 422insufficient_
funds doesn't hold enough of the token (or SOL, for a native payment): top up
- 422insufficient_
native_ funds can't pay the network fee (ETH, SOL…): top up the network's coin
- 422insufficient_
allowance granted QBitFlow less than this amount: increase the allowance
- 422allowance_
expired granted an allowance that expired: approve again
- 422token_
not_ approved hasn't approved Permit2 for the token (EVM): approve it, then retry
- 422signature_
expired signed too long ago: sign again (a free trial's message: ask a new intent)
- 422max_
amount_ exceeded a bill above the subscription's maximum per period (the price moved): approve a higher maximum
- 422allowance_
too_ low asked for an amount outside the subscription's limits (
allowance_, Solana only: a top-up of fewer periods than were spent since the last one granted, which its program refuses until its upgrade;too_ low details., the fewest periods it takes)minPeriods - 422tx_
failed can't act: the transaction failed for a reason no decoder recognized