Skip to main content

Fee & credit reads

Read queries on POST /info. The endpoint, the request envelope, the number planes and the error shape are on that page and apply to every query here.

Volume-tiered maker and taker fees

Returns the maker/taker fee schedule and its volume tiers.

Request

{ "type": "fee_schedule" }
ArgTypeRequiredMeaning
addresshex addressnoAdds the per-account user block described below
daysuintnoBounds user.daily_volume to its newest days buckets. Range 1 to 30. Default 30

days does nothing without an address, because only the user block carries a series. A days that is not an integer in 130 does not fail — it falls back to the full 30-day window. That is deliberate: a typo cannot turn the series into an empty array.

Response

{
"data": {
"type": "fee_schedule",
"tiers": [
{ "volume_30d": "0", "maker_bps": "2.0", "taker_bps": "5.0" },
{ "volume_30d": "100000000", "maker_bps": "1.5", "taker_bps": "4.5" },
{ "volume_30d": "1000000000","maker_bps": "1.0", "taker_bps": "4.0" }
],
"pooled_volume_sunset_day": 20340,
"pooled_volume_sunset_ms": "1757376000000",
"pooled_volume_counts": true,
"burn_ratio": "0.30",
"referrer_share_bps": "1.0"
}
}
FieldTypeMeaning
tiers[*].volume_30dDecimal string30-day trailing volume threshold for this tier
tiers[*].maker_bpsDecimal stringMaker fee rate at this tier, in basis points
tiers[*].taker_bpsDecimal stringTaker fee rate at this tier, in basis points
pooled_volume_sunset_dayuint64The day the pooled volume counter stops buying a discount. 0 = not armed yet
pooled_volume_sunset_msDecimal stringThe same instant in milliseconds. "0" = not armed yet
pooled_volume_countsbooltrue while pooled volume still feeds a tier
burn_ratioDecimal stringFraction of fees burned
referrer_share_bpsDecimal stringReferrer's share of fees, in basis points

Rules

  • Fee rates are decimal basis points as strings with one fractional digit (e.g. "2.0" = 2 bps = 0.02%, "0.5" = 0.5 bps = 0.005%), for sub-basis-point precision.
  • burn_ratio is a decimal fraction ("0.30" = 30% of fees burned).
  • There is no builder-rebate field on this read, and there is no protocol rebate to a broker. A broker is paid the builder.fee it sets on each order, and that rate is capped by the ceiling the trader granted it — read the ceiling from approved_brokers max_fee_bps. The broker fee is charged ON TOP of the schedule above, so no field here changes when a broker is paid. See broker codes.

Send an address to get that account's resolved rates. The response then also carries a user block:

{
"data": {
"type": "fee_schedule",
"tiers": [],
"user": {
"address": "0x<addr>",
"taker_volume_30d": "12500000",
"maker_volume_30d": "3100000",
"taker_bps": "4.5",
"maker_bps": "1.5",
"effective_taker_bps": "4.05",
"effective_maker_bps": "1.2",
"staking_discount_permille": 100,
"maker_rebate_bps": "0.3",
"vip_tier": 0,
"mm_tier": 0,
"referrer": null,
"referrer_credit": "0",
"products": [
{ "product": "perp", "taker_bps": "4.05", "maker_bps": "1.2",
"taker_volume_30d": "12500000", "maker_volume_30d": "3100000" },
{ "product": "spot", "taker_bps": "9.0", "maker_bps": "2.0",
"taker_volume_30d": "12500000", "maker_volume_30d": "3100000" },
{ "product": "spot_margin", "taker_bps": "9.0", "taker_volume_30d": "12500000" },
{ "product": "option", "option_taker_bps": "0.5", "option_premium_cap_ppm": 150000 }
],
"daily_volume": [
{ "day": 0, "taker_volume": "1416854.124376258", "maker_volume": "0",
"exchange_maker_volume": "140430596.722835936" }
]
}
}
}
FieldTypeMeaning
user.taker_volume_30dDecimal stringPooled trailing 30-day taker volume, every product together
user.maker_volume_30dDecimal stringPooled trailing 30-day maker volume
user.taker_bps / maker_bpsDecimal stringThe PERP base rate, before the discount and the rebate
user.effective_taker_bpsDecimal stringThe PERP rate a fill charges, discount applied
user.effective_maker_bpsDecimal stringThe PERP rate a fill charges, rebate subtracted. Negative = a credit
user.staking_discount_permilleuint32Taker-only staking discount, per mille (100 = 10%)
user.maker_rebate_bpsDecimal stringThe PERP maker rebate, before it is subtracted
user.vip_tieruintThe account's VIP-tier override index. 0 when the account holds no override, which is the common case
user.mm_tieruintThe account's market-maker-tier override index. 0 when the account holds no override
user.referrerhex address | nullThe referrer this account is bound to. null, not absent, when the account is bound to nobody
user.referrer_creditDecimal stringCredit this account has accrued AS a referrer, whole USDC. It is the credit owed TO this address, not the discount it receives
user.daily_volumearrayPer-day volume buckets, oldest day first. See the rules below
user.daily_volume[*].dayuint64Consensus day index, that is consensus_time_ms / 86400000. It is not a calendar date and not an offset from today. 0 is a real day index, not an unset marker — a bucket rolled at consensus time zero reports 0, and the current chain serves such a row
user.daily_volume[*].taker_volumeDecimal stringThis account's taker volume on that day
user.daily_volume[*].maker_volumeDecimal stringThis account's maker volume on that day
user.daily_volume[*].exchange_maker_volumeDecimal stringExchange-wide maker volume on that day. There is no exchange-wide taker total — do not read this as total traded volume
user.products[*].productstringperp, spot, spot_margin or option
user.products[*].taker_bpsDecimal stringThe rate a fill on THIS product charges, discount applied
user.products[*].maker_bpsDecimal stringThe rate a fill on THIS product charges, rebate subtracted. ABSENT on a product with no maker leg
user.products[*].taker_volume_30dDecimal stringThe volume THIS product's tier reads
user.products[*].maker_volume_30dDecimal stringThe volume THIS product's maker tier reads. ABSENT on a product with no maker leg
user.products[*].option_taker_bpsDecimal stringOPTION ROW ONLY. The rate charged on the option's STRIKE FACE (strike x size), for puts and calls alike
user.products[*].option_premium_cap_ppmuint32OPTION ROW ONLY. The fee ceiling as a fraction of the premium, in ppm

The four products price apart. Read products, not the top-level pair. The top-level effective_*_bps fields are the PERP rate, which is what they have always meant. A spot or an option fill can charge a different rate. See Each product has its own fee table.

The option row has a DIFFERENT shape, because an option does not price on a volume ladder. It carries no taker_bps and no volume; instead it carries option_taker_bps and option_premium_cap_ppm, and the fee charged is the SMALLER of a rate on the option's strike face and that fraction of the premium. Both start unset, which charges nothing. The strike face is strike x size on BOTH kinds: a call escrows one coin, whose dollar worth the chain cannot read without a price, so the strike is the notional it uses. The fee is charged in USDC on both kinds. See the option fee.

A row with no maker_bps has no maker leg. A maker rests on the shared spot book and never carries a lane, so a maker is always priced as spot. That leaves spot_margin and option with a taker leg only, and those two rows omit both maker keys rather than render a rate nothing can charge.

Every products[*] row can carry the same volume today, and later cannot. Until the pooled window sunsets, a product's tier reads the LARGER of your pooled volume and the volume you traded on that product, so the rows agree. After the sunset each row reads only its own product. pooled_volume_sunset_ms in the same response is the date; the rule is in the pooled window.

daily_volume is SPARSE. A quiet day has NO ROW — it is not a zero row. All three series roll only when a fill charges a positive protocol fee. A zero-fee market and a fully rebated maker leg never reach them. So a day on which the account traded can still be missing, and a gap does not mean the account was idle. Index the array by day; never assume row n is n days ago, and never assume the array length is the number of days elapsed.

The rows are a UNION of three sources: the account's taker buckets, its maker buckets, and the exchange-wide maker buckets. A day that carries only exchange volume still appears, with the account's own two figures at "0". Those zeros are real zeros; a missing day is not.

days bounds each source separately, not the union. Each of the three sources contributes its own newest days buckets. The three ranges can be disjoint, so the returned array can hold more than days rows. Treat days as a bound on work, not as an exact row count.

See fees.

Accrued referral credit for one account

One account's claimable referral credit, and the referrer it is bound to.

The parameter is user, not address. Most reads on this page take address. These two fee-credit reads take user. Sending address answers 400 INVALID_REQUEST, with details.field set to user.

Request

{ "type": "referral_state", "address": "0x<addr>" }
ArgTypeRequiredMeaning
userhex addressyesThe account to read

Response

{
"data": {
"type": "referral_state",
"user": "0x00000000000000000000000000000000000ca11e",
"claimable_rewards": "12.451",
"referrer": "0x00000000000000000000000000000000000000bb"
}
}
FieldTypeMeaning
userhex addressThe account read, echoed back
claimable_rewardsDecimal stringUSDC credit this account can claim right now
referrerhex address | nullThe referrer this account is bound to. null = never bound

Rules

  • Read the credit here before you claim it. The claim action reports no amount. claim_referral_rewards drains the whole balance and answers with no figure, so this read is the only way to show a claimable balance or to decide whether a claim is worth sending.
  • claimable_rewards of "0" is normal, not an error state. Claiming with nothing accrued claims 0 and succeeds. Do not block the button on it.
  • referrer: null means the account never bound one. It does not mean the node is old and it does not mean the referrer is unknown. A referrer is bound once with set_referrer and is immutable after that, so null is a durable answer until the account sends that action.
  • This read cannot list the accounts YOU referred. The referral graph is address-based and one-directional: the chain stores each referee's referrer, and no reverse map. There is no read that enumerates a referrer's referees, and no referral code to enumerate them by. Track your own referees off-chain.
  • claimable_rewards can under-report what a referrer earned. A referrer share on a spot BUY arrives in the base token, paid at the fill, and a base amount cannot join this USDC-denominated credit. Only the USDC shares accumulate here. See in-kind fees.

Accrued broker credit for one account

One broker's claimable broker-code fee credit.

Request

{ "type": "broker_state", "address": "0x<addr>" }
ArgTypeRequiredMeaning
userhex addressyesThe broker account to read

Response

{
"data": {
"type": "broker_state",
"user": "0x00000000000000000000000000000000000000aa",
"claimable_rewards": "308.9"
}
}
FieldTypeMeaning
userhex addressThe account read, echoed back
claimable_rewardsDecimal stringUSDC credit this broker can claim right now

Rules

  • Read the credit here before you claim it. The claim action reports no amount. claim_builder_rewards drains the whole balance and answers with no figure.
  • builder_state is the old name and still answers. Send broker_state. The reply echoes back whichever name you sent.
  • A broker credit and a referral credit are separate balances with separate claims. One fill can pay both. Reading one tells you nothing about the other. See broker credit is not referrer credit.
  • This is a credit balance, not a fee rate. The rate a broker charges is the builder.fee on each order, capped by its approved_brokers grant.