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
| Field | Description |
|---|---|
id | txn_ followed by digits. An exact id lookup accepts the value with or without the prefix. |
type | Business type; see the table below. Open enum. |
status | The original status value from the corresponding product. See the warning below. Open enum. |
status_version | Monotonically increasing. Use this to merge states; see below. |
direction | in / out. Closed enum; other values return 400. |
asset | Asset code |
amount | Fixed-point string, with precision specified by amount_scale. Always positive; use direction for the direction. |
occurred_at | When the event occurred; for deposits, when it was detected. |
created_at | When the transaction row was stored. Sorting and filtering use this field. |
Current type values
| Value | Direction | Meaning |
|---|---|---|
deposit_crypto | in | On-chain deposit credited |
withdrawal | out | On-chain withdrawal |
remittance | out | Remittance |
qrpay | out | QR payment |
exchange | in / out | Internal conversion (two rows per order; see below) |
internal_transfer | in / out | Internal transfer |
card_issue_fee | out | Card issuance fee, including physical-card postage |
card_refund | in | Fee refund after failed card issuance |
card_penalty | out | Card penalty |
card_topup | in / out | Card top-up (two rows per order; see below) |
card_withdraw | in | Withdrawal from a card, returning USD to the wallet |
card_txn | in / out | Card transaction |
earn_subscribe | out | Wealth subscription |
earn_redeem | in | Wealth redemption |
earn_interest | in | Wealth interest distribution |
balance_adjust | in / out | Balance adjustments and reversals performed by our operations team |
⚠
withdrawal(on-chain withdrawal) andcard_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
typewithout a version release or notification. Therefore:
- Your
switchmust include adefaultbranch. Thedefaultbranch should **record the movement usingdirectionand
amountand 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:
- Do not compare
statusacross transaction types.?status=completedmatches only certain types. - Interpret success and failure per type, or use the product-specific detail endpoint.
- Display unrecognized values as received. Do not default them to “processing”, which could make a failed order appear to be in progress.
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_atas the incremental synchronization watermark. A row with an earlyoccurred_atbut 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.