Fees
Volume-based maker/taker tiers, in percent, straight from the fee engine — with a maker rebate at the top tier.
Trading fees are volume-based. Your tier is set by your 30-day rolling trading volume (in CAD); higher tiers pay lower fees, and the top tier earns a maker rebate (a negative maker fee — you are paid to provide liquidity). A maker adds resting liquidity to the book; a taker removes it.
Schedule
Rates are percentages of the traded notional (the engine divides by 100 internally — a
2.00 taker rate is 2%). This table is generated from FEE_TIERS in
app/services/fee_service.py and drift-gated in CI.
At the Diamond tier the maker rate is negative — a rebate credited to makers who post liquidity.
How a rate is chosen
The tier table above is the base. A market or a category can carry its own schedule, and
a promotional window can cap what either of them charges. The engine picks the most specific
rule that applies, then applies the promotional stages last. This block is generated from the
same constants the /fees endpoints serve, so it cannot drift from the engine.
Applied after resolution, in this order — both can only ever reduce:
Sign rules worth knowing: a per-market or per-category schedule is never negative, so an
override replaces the Diamond maker rebate with a real (possibly zero) fee. A promotional
window is applied as fee = min(fee, window fee) — it can bring a fee down to zero, but it
never enlarges a rebate. A per-user fee-rebate entitlement then takes basis points off
whatever remains, floored at zero.
Per-market and per-category schedules, and promotional windows, are feature-flagged. In
an environment where they are off, GET /fees/schedule returns an empty resolution_order
and every rate comes from the tier table above.
Scope today. Overrides and windows are resolved wherever the caller supplies market
context — GET /fees/preview, the fee breakdown on a receipt, and the admin console.
Order-book and AMM fills are still priced from the volume tier: the matching engine’s
fee call sites do not yet pass the market they are filling. Until that lands, treat
/fees/preview as authoritative for scheduled pricing and the execution receipt as
authoritative for what a fill actually charged. This page will drop this warning when the
two agree.
Previewing the fee for a specific trade
GET /fees/preview runs the resolver above and returns the effective maker_pct and
taker_pct, the source that set them, any promotional window with its expiry, and — when
you pass quantity and price — the estimated_fee on that notional, rounded exactly as the
engine rounds it.
Authentication is optional and the response says which basis you got: authenticated uses
your own tier and entitlements, anonymous_bronze_baseline quotes the entry tier. Rate limit:
120 requests/minute. Source: app/api/routes/fees.py.
Reading your fees over the API
Two public endpoints expose the schedule and your current standing:
GET /fees/schedule returns all tiers plus the current withdrawal fee percentage;
GET /fees/my-tier returns your tier name, maker/taker rates, 30-day volume, and progress to
the next tier. Source: app/api/routes/fees.py.
Quotes are authoritative
Before placing an order you can preview a fee-inclusive quote (preview_order_quote in
the SDKs). The fee shown in the quote is the fee that will be charged, and the quote token
binds it when you place the order — so the disclosed fee equals the charged fee. Fees round
up to the cent in the platform’s favour (How pricing works); treat
the quote and the execution receipt the API returns as the source of truth rather than
recomputing fees client-side.
An admin can globally override the maker/taker rates; when an override is active it applies
in place of the tiered rates above. The GET /fees/* endpoints always reflect the rates
actually in effect.

