Z Zise Developers 简体中文

Transaction history is a projection of the ledger. Each row represents a real funds movement. This page lists the field values.

Transaction History


GET /v1/transactions?external_member_id=…&cursor=…

This endpoint uses cursor pagination. See Pagination.

Fields

FieldDescription
idtxn_ followed by digits. An exact id lookup accepts the value with or without the prefix.
typeBusiness type; see the table below. Open enum.
statusThe original status value from the corresponding product. See the warning below. Open enum.
status_versionMonotonically increasing. Use this to merge states; see below.
directionin / out. Closed enum; other values return 400.
assetAsset code
amountFixed-point string, with precision specified by amount_scale. Always positive; use direction for the direction.
occurred_atWhen the event occurred; for deposits, when it was detected.
created_atWhen the transaction row was stored. Sorting and filtering use this field.

Current type values

ValueDirectionMeaning
deposit_cryptoinOn-chain deposit credited
withdrawaloutOn-chain withdrawal
remittanceoutRemittance
qrpayoutQR payment
exchangein / outInternal conversion (two rows per order; see below)
internal_transferin / outInternal transfer
card_issue_feeoutCard issuance fee, including physical-card postage
card_refundinFee refund after failed card issuance
card_penaltyoutCard penalty
card_topupin / outCard top-up (two rows per order; see below)
card_withdrawinWithdrawal from a card, returning USD to the wallet
card_txnin / outCard transaction
earn_subscribeoutWealth subscription
earn_redeeminWealth redemption
earn_interestinWealth interest distribution
balance_adjustin / outBalance adjustments and reversals performed by our operations team

⚠ withdrawal (on-chain withdrawal) and card_withdraw (withdrawal from a card) are different operations.

The former moves funds out of the ledger; the latter moves funds from the card back to the wallet.

⚠ This is an open enum. A new product may introduce a new type

without a version release or notification. Therefore:

- Your switch must include a default branch. The default branch should **record the movement using direction and

amount and display the original value**, rather than discard it or raise an error.

- An unknown value in ?type= returns an empty list, not 400.

This preserves the behavior of an open enum.


status preserves product-specific values

status comes directly from the corresponding product's detail table. Deposits and wealth products, for example, have their own status values. They are not reduced to success / pending / failed.

This is intentional. Reducing them to three states would make “under manual review” and “awaiting provider confirmation” indistinguishable, even though the user-facing explanations should differ.

Accordingly:


Two transaction types have two rows per order

Conversions (exchange) and card top-ups (card_topup) each generate two rows: the debit leg (direction: out) and the credit leg (direction: in).

They represent the same transaction.

⚠ Do not count them as two separate transactions in your statistics. When calculating how much a member sent out during a month,

including the debit leg of a conversion would count a 100 USDT → USD conversion as both

“100 sent” and “99.x received”, even though no funds left your system.

Our App hides the credit leg in the combined transaction list. The Open API returns both rows,

providing a complete ledger projection rather than a presentation-oriented list.


status_version: the sole criterion for merging states

You may receive the state of one order through webhooks, this list and the product detail endpoint. Their arrival order is not guaranteed.

State merging must only move forward:


if (incoming.status_version > stored.status_version) apply(incoming)

⚠ Without this check, a late response can change “credited” back to “processing”.

This is difficult to reproduce in a fast local test environment.


Incremental synchronization uses created_at


GET /v1/transactions?from=<上一轮见过的最大 created_at>

from / to and the cursor all use created_at, not occurred_at.

⚠ Do not use occurred_at as the incremental synchronization watermark. A row with an early occurred_at

but a late created_at, such as a backfilled historical transaction, would be permanently skipped.


Reconcile using transactions, not balances

A balance is a point-in-time snapshot; transactions record the movements. To calculate total monthly spending, use transaction history. Subtracting two balance snapshots would miss deposits made during the same period.

Related endpoints