Skip to main content

Rebate Records

Query the list of invitees and rebate commission data through the following endpoints:

  • Referral Status — View all referred users and binding status
  • Referral Dashboard — View commission summary and downline counts
  • Referral Logs — Paginated history of all referral operations (create, bind, unbind, claim)
  • On-Chain Rebate Info — Query on-chain rebate data directly from smart contracts
  • Traders / Affiliates / Claims — V2 endpoints documented below

Commission Calculation

When a referred trader (referee) executes a trade, the commission is calculated as:

commission = trade_fee × tier_commission_rate

Both maker and taker fees generate separate commission records if the respective trader has a referrer.

Earnings Status Model

Each referral_earnings row carries two independent status columns:

status — claim lifecycle

StatusDescription
pendingAccrued, not yet claimed
claimedRedeemed on-chain — set when the backend observes the contract's RewardRedeemed event (claimed_at recorded)

chain_sync_status — on-chain settlement sync

StatusDescription
pendingNot yet batch-synced to the contract
syncedIncluded in a successful batchSettleRewards transaction (chain_sync_tx recorded)
failedSync failed after 3 attempts (chain_sync_error recorded)

An earning is claimable only when chain_sync_status = 'synced' AND status = 'pending'.

Claim orders (commission_claims) have their own status: processing (created, awaiting on-chain redeem) → success (redeem confirmed, tx_hash/finished_at set). Failed claims carry a failure_reason and can be retried by admin.

Minimum Claim Amount

The minimum claim amount is 10 USDT. Claims below this threshold return a BELOW_MINIMUM error.

Batch On-Chain Sync

Pending referral earnings are batch-synced to the on-chain ZtdxRewardRouter contract every 5 minutes via batchSettleRewards. Once synced, earnings become claimable through POST /api/v1/referral/claim.


V2 Endpoints

All endpoints below require a JWT Bearer token.

List Traders

Lists the referrer's directly bound traders (is_affiliate = false) with per-trader volume and commission aggregates.

GET /api/v1/referral/traders
Authorization: Bearer <token>

Query Parameters

ParameterTypeDefaultDescription
bizstringallBusiness filter: all / spot / futures
timestringallTime window for aggregates: all / 7d / 30d
qstringSubstring filter on the trader address (optional)
pageint1Page number (minimum 1)
page_sizeint20Items per page (1–100)

Response

{
"items": [
{
"address": "0xabc...",
"bound_at": "2026-03-01T10:00:00Z",
"spot_volume": "120.00",
"futures_volume": "380.00",
"spot_commission": "12.00",
"futures_commission": "38.00",
"total_commission": "50.00",
"last_trade_at": "2026-04-15T09:00:00Z",
"status": "active"
}
],
"total": 8,
"page": 1,
"page_size": 20
}
FieldTypeDescription
items[].addressstringTrader's wallet address
items[].bound_atstringWhen the trader bound to the referrer (ISO 8601)
items[].spot_volume / futures_volumestringAggregated fee value attributed to this trader from the referrer's earnings records, per business line
items[].spot_commission / futures_commissionstringSynced commission earned from this trader, per business line
items[].total_commissionstringspot_commission + futures_commission
items[].last_trade_atstring | nullMost recent earning-generating trade
items[].statusstringactive if the last trade is within 7 days, else inactive
totalint64Total direct traders (not affected by filters)

List Affiliates

Lists the referrer's downline affiliates (is_affiliate = true) with team and spread commission aggregates.

GET /api/v1/referral/affiliates
Authorization: Bearer <token>

Query Parameters

ParameterTypeDefaultDescription
pageint1Page number (minimum 1)
page_sizeint20Items per page (1–100)

Response

{
"items": [
{
"address": "0xdef...",
"sub_rate": "0.05",
"spread_rate": "0.05",
"direct_traders_count": 3,
"team_volume": "500.00",
"spot_spread_commission": "5.00",
"futures_spread_commission": "20.00",
"total_spread_commission": "25.00",
"status": "active"
}
],
"total": 1,
"page": 1,
"page_size": 20
}
FieldTypeDescription
items[].sub_ratestringRate passed down to the affiliate
items[].spread_ratestringYour spread on that affiliate's team: my_rebate_rate − sub_rate (floored at 0)
items[].direct_traders_countint64Number of the affiliate's own direct traders
items[].team_volumestringAggregated fee value from the affiliate's team (spread-type earnings)
items[].spot_spread_commission / futures_spread_commissionstringSynced spread commission per business line
items[].total_spread_commissionstringSum of the two spread commissions
items[].statusstringCurrently always "active"

Promote a Trader to Affiliate

POST /api/v1/referral/affiliates
Authorization: Bearer <token>
Content-Type: application/json
{ "wallet": "0xdef...", "sub_rate": "0.05" }
FieldTypeRequiredDescription
walletstringYesAddress of one of your direct traders
sub_rateDecimalYesRate passed to the affiliate; must satisfy 0 ≤ sub_rate ≤ your rebate_rate

Response: { "ok": true }

HTTPCodeDescription
400SELF_ASSIGNMENTCannot promote yourself
400SUB_RATE_EXCEEDS_OWNsub_rate is negative or exceeds your own rebate rate
400USER_NOT_FOUNDTarget wallet is not a registered user
400TARGET_NOT_AGENTTarget must first be an active tier-1 agent
400TARGET_NOT_DIRECT_TRADERTarget wallet is not your direct trader
400ALREADY_AFFILIATETarget is already an affiliate

Update Affiliate Sub-Rate

PUT /api/v1/referral/affiliates/:wallet
Authorization: Bearer <token>
Content-Type: application/json
{ "sub_rate": "0.06" }

Response: { "ok": true }

HTTPCodeDescription
400SUB_RATE_EXCEEDS_OWNsub_rate is negative or exceeds your own rebate rate
404AFFILIATE_NOT_FOUNDNo affiliate relation with this wallet

Claim Preview

GET /api/v1/referral/claims/preview
Authorization: Bearer <token>
{
"claimable": "45.00",
"pending": "12.50",
"last_claimed_at": "2026-04-10T08:15:00Z",
"claim_wallet": "0xabc..."
}
FieldTypeDescription
claimablestringCommission claimable now (chain_sync_status='synced' AND status='pending')
pendingstringCommission awaiting on-chain sync (chain_sync_status='pending')
last_claimed_atstring | nullFinish time of the latest successful claim
claim_walletstringWallet the claim would pay to (the authenticated address)

List My Claims

GET /api/v1/referral/claims
Authorization: Bearer <token>

Query Parameters

ParameterTypeDefaultDescription
pageint1Page number (minimum 1)
page_sizeint20Items per page (1–100)

Response

{
"items": [
{
"claim_no": "CLM-1a2b3c4d5e6f",
"amount": "45.00",
"status": "success",
"tx_hash": "0x...",
"failure_reason": null,
"applied_at": "2026-04-10T08:00:00Z",
"finished_at": "2026-04-10T08:15:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 20
}
FieldTypeDescription
items[].claim_nostringClaim order number
items[].amountstringClaim amount (USDT, decimal string)
items[].statusstringprocessing / success
items[].tx_hashstring | nullOn-chain redeem transaction hash
items[].failure_reasonstring | nullFailure detail, if any
items[].applied_atstringWhen the claim order was created
items[].finished_atstring | nullWhen the on-chain redeem was confirmed