Risk & inventory
A perps maker uses a trader account with a quoting slot. Each fill changes the account's position. Maker positions follow the same margin, funding, and liquidation rules as taker positions.
Operating controls
Set limits and failure responses in your bot before you enable quotes.
| Condition | Response |
|---|---|
| Free collateral is too low for the intended fills | Reduce quote size or exposure. Do not use maintenance-margin headroom as a quote-size allowance. |
| Net equity reaches your maintenance-margin alert threshold | Reduce exposure or add collateral. Disabling quotes does not close existing positions. |
| Your price source stops or its data is stale | Stop refreshing quotes and disable them. If the disable cannot land, existing quotes remain subject to their expiry. |
| Account health is unavailable or stale | Stop refreshing quotes and disable them until current health data is available. |
| A quote update fails or exceeds your latency limit | Check transaction status and accepted slot state. An unsuccessful update leaves the previous quote active until expiry. |
| You stop, restart or rotate a writer | Follow Stop quote writes. Reconcile pending transactions before the final disable or a sequence reset. |
| A quoting key is compromised | Revoke its on-chain delegate authority. Also disable its stored quotes and cancel resting orders; revocation does not remove them. |
For account calculations, see Collateral & margin, Funding and Liquidations.
One account, cross-margined
Account health includes every asset and perp in your trader account. All its perps use the same collateral. A loss on one perp reduces the collateral available for the others. Check both margin thresholds:
- Initial margin: you need
net_equity ≥ initial marginto increase exposure. - Maintenance margin: once
net_equityfalls below it, the account can be liquidated.
Initial margin is always at least maintenance margin. Between the two thresholds, you can reduce exposure but cannot increase it.
Margin at fill time
The program checks margin separately for each quoted level the taker reaches. Perps have no per-market inventory balance or spot-style soft cap.
The program first limits the level's quantity to the position cap. It then checks whether your account can support the whole remaining level, before and after the fill:
- a fill that grows your position must leave you at or above initial margin;
- a fill that reduces it must leave you at or above maintenance;
- a fill that flips the position through zero must meet initial margin for the whole fill.
A fill priced worse than the mark (a bid above it, an ask below it) reduces the equity available for the margin check. The program accounts for the adverse price difference as a debit to the PnL-currency balance. It excludes the maker rebate from this check, so the rebate cannot make an otherwise unfillable level pass.
If the full level fails the margin check, none of it is offered. No deeper level on that side is offered to that taker order, even if it is smaller. The taker's order can continue to other makers. An account already below maintenance margin offers no fillable quote.
If you also rest limit orders on the perp's order book, your quote and your orders share one margin allowance per taker order. An order that fails its margin check is skipped, so later orders can still trade. See Quoting → Quotes and resting orders.
Your own leverage cap
Use set_account_leverage_cap to set a maximum account leverage
(stored as 1 / max_leverage; 0 removes the cap). The owner
or a Trade delegate sets it. Once set, every fill that grows
exposure, quote fills included, must also leave
net_equity ≥ leverage_cap × net_exposure. A quoted level that fails
this check is refused whole, and deeper levels are not offered for that
taker order. The leverage cap does not apply to reducing fills or to
the maintenance-margin check.
Caps and limits
Each listing can cap one trader's net position with max_position_lots.
The following limits also apply:
| Limit | Scope | Effect |
|---|---|---|
| Margin | Your account | A level that fails the margin check prevents deeper quote levels on that side from filling for that taker order. |
Leverage cap (set_account_leverage_cap) | Your account, if you set one | A quoted level that would increase exposure beyond the cap is refused whole; deeper quote levels are not offered for that taker order. |
Position cap (max_position_lots) | Each trader on the perp | Caps net lots in either direction; reductions remain possible. |
Open-interest cap (max_open_interest_lots) | Each perp | A trade that would push the perp's open interest past the cap is refused. |
Position slots (max_positions) | Your account | If your account has no room for a new perp position, your slot is skipped on that perp's orders. A perp with only resting orders also uses a position slot. |
| Makers per perp | Each perp's quoting account | 32 slots. A new maker can open one only if a slot is available. |
| Slot capacity | Your quoting slot | 21 order-list levels or 30 density bands per side. |
| Resting orders | Your account, per perp | 16 orders per trader per perp. |
| Density fill risk | Your quoting slot | Filled lots remain subtracted from the ticks nearest your fair until a Reset; see Quoting → Fill risk. |
The density fill counter reduces available depth near the fair after fills on that side. It never decreases on its own. Decide when to reset and restore depth; do not reset automatically on every refresh cycle.
Inventory and funding
Every fill changes your position. The program does not rebalance it.
Track fills with SubscribeFills and reconcile positions against account
state. Adjust your fair prices to encourage fills that reduce inventory.
A density quote lets you move bid_fair and ask_fair independently
without rewriting bands.
Open positions pay or receive funding. Funding accrues on your net position, including fills from quotes and hedges on Flint. See Funding for the rate and settlement interval.
Liquidation
Monitor liquidation risk for your account and for accounts that can fill your quotes.
Your own account. Below maintenance margin your quote offers no fillable
levels, and the account can be liquidated. Permissionless keepers can close
part of your perp positions and seize collateral for a bonus. See Liquidations.
Before liquidation, once you are below initial margin, anyone can cancel
your margin-reserving resting orders with force_cancel_perp_orders.
Size quotes to your free collateral. Disable quotes when account
health no longer supports the intended fills.
Another account. A liquidation closes the distressed account's position against makers' resting quotes, with the liquidated account as the taker. Unlike an ordinary order, a liquidation must include every enabled maker slot on that perp. Its fills still require the maker margin checks described above. The liquidator chooses which resting order accounts to include. In a fast move, liquidation orders can fill at your quoted prices. Choose prices and sizes that your account can support during a series of liquidations.
Hedging
Choose a hedge method for your inventory:
- Skew quotes. Adjust your fair prices to encourage fills that reduce inventory.
- Hedge elsewhere. Hedge your net position on another venue. Collateral there does not support margin on Flint. Size your Flint quotes to Flint's free collateral alone.
- Hedge on Flint. The quoting key's
Tradescope also lets it placeIocorFokimmediate orders, orGtcandGtdresting orders. Setpost_onlyon a resting order to reject an immediate crossing. Setreduce_onlyto allow only position reductions (see Orders). An order cannot cross your own slot or orders; self-matching is refused. Leave your own trader account out of the makers it crosses.
Funding continues to accrue on your net position on Flint while it is open.
Monitoring
MakerService and TxService use your bot's bearer session.
AccountService and PerpMarketService are public. See
Quoting → Watching fills for fields.
| What | Where |
|---|---|
| Fills as they happen | MakerService.SubscribeFills |
| Fill history | MakerService.GetFills (paged) |
| Your best bid and ask alongside the order book | MakerService.SubscribeMarketSnapshots |
| Slot state: enabled, strategy, sequences | MakerService.GetQuotingState |
| Quote writes observed on chain | MakerService.SubscribeQuotes / ListRecentQuotes |
| Send, land and fail rates; fill and quote-update rates | MakerService.GetStats |
| Markouts | MakerService.GetMarkoutSummary, or GetFills sorted by markout |
| Keys and sessions quoting for you | MakerService.ListQuotingAuthorities / ListQuoterSessions |
| Maker volume by perp and window | MakerService.GetVolumeBreakdown / GetVolumeSeries |
| Transaction landing and failure status | TxService.SubscribeTxStatus |
| Collateral, account health, positions, margin | Public AccountService.GetAccount / SubscribeAccount; see Positions & PnL |
| Mark, index and funding rate per perp | PerpMarketService.GetMarketStats (poll; SubscribeMarketStats is not served yet) |
ListQuotingAuthorities and ListQuoterSessions show the keys the
server has observed quoting or holding a live session heartbeat for
your trader, with regions, SDK versions, round-trip times and last
submission and landing times. These lists can omit a key that authenticates
but never sends a heartbeat or transaction. Investigate any entry you
do not recognize. Revoke unauthorized delegate keys on chain. To audit
every key with authority, read your delegate accounts on chain.
If transactions stop landing or a Flint feed stops updating, use
EscalationService.PageTheTeam to send a message to Flint's on-call team
(client.escalation() in Rust). The trader must be linked to your
organization. Otherwise, the call returns PERMISSION_DENIED.
Alert on at least:
- free collateral and initial-margin headroom: compare net equity
with initial margin before adding exposure. Free collateral is
max(net_equity - initial_margin, 0); - maintenance-margin headroom: compare net equity with maintenance margin to monitor liquidation risk;
- submit-to-land latency and failures on your quote transactions: failed updates leave the previous quote active until expiry;
- the quoting key's SOL balance: Flint supplies fee SOL. If that balance is too low, quote updates fail and the existing quotes expire;
- price-source age and fair versus mark: stop refreshing quotes when price data exceeds your age or deviation limits.
Operational safety
Key hygiene
| Key | Holds | Can | Keep |
|---|---|---|---|
| Owner | Account ownership | Deposit, withdraw, delegate, revoke, quote and trade | Offline: hardware wallet or multisig |
| Quoting key | Trade + Quote delegate | Sign in, quote, enable/disable, open and release slots, place and cancel orders, set the leverage cap | On the bot host, with Flint-provided fee SOL |
A stolen quoting key can quote and trade your account into losses.
It has no withdrawal authority when it has only Trade and Quote.
Limit its permissions and monitor its activity:
- Never grant
WithdraworBorrowLendto a quoting key. - Set an expiry on the delegate (
expiry_unix_secondsin Rust,expiryUnixSecondsin TypeScript). Rotate to a new funded key before it expires. An existing delegate grant cannot be renewed withcreate_delegate_trader_account. - Watch unexpected fills, as well as your own submissions:
any transaction signed by the key acts on the account, whether or
not it went through
TxService.
The downloadable examples set the delegate expiry to 0, which means
no expiry. To create an expiring grant, change that argument
to the intended absolute Unix timestamp before running setup with a
new key.
For a planned key rotation, first follow
Stop quote writes, then the
key rotation procedure. Sequence numbers
belong to the slot,
so the new writer must read order_sequence and fair_sequence from
GetQuotingState and allocate higher counters. The Rust QuotingCore
does this on startup. Also set QuotingConfig::delegate_trader_account
to the new key's delegate account.
Revocation permanently removes that key's delegate authority on this trader account. The delegate account remains allocated with empty permissions. You cannot grant that key again on the same trader account. This prevents an old signed intent from being replayed against a new grant.
Revocation does not disable stored quotes or cancel resting orders. Use the owner or another authorized key to remove them. A revoked key cannot submit those cleanup transactions.
Revoking an API session (AuthService.Revoke, or revoke() on the
SDK's AuthFlow) invalidates that bearer token. The key retains its
on-chain authority and can submit transactions through an RPC node
until you revoke its delegate authority.
Stale quotes
A quote can remain fillable until it expires, you disable it, or it is rewritten. The program does not compare your fair to the mark or an oracle to detect stale quote prices:
- Use short expiries.
slot_delta_expiryon density bands (from the fair's stamp) andslot_expiryon order-list levels are your automatic expiry controls. If your bot, network orTxServicepath fails, quotes expire without another transaction. - Do not re-stamp a fair without a current price source. A fresh slot extends expiry even if the price is stale. If your price source fails, stop the update loop and disable the quote. If you cannot submit a disable, the quote remains subject to its existing expiry.
- Disable on shutdown. Follow Stop quote writes before the final disable. Confirm that each live slot is disabled and that resting orders are canceled on each perp. Keep an authorized key available until this is complete.
- Recover sequence counters. Read the accepted value before restarting a writer. If it cannot advance, use the guarded sequence reset.
Stale prices
Each perp's mark is published from the oracle and is valid only for a
fixed window. Once it expires, the program refuses orders on that perp
with LinearPerpMarkExpired until a keeper publishes a fresh mark.
No quote fills during this period. Your slot state does not change.
When the mark becomes valid again, unexpired quotes can become fillable immediately. If your own fair stopped updating during the outage, check that the quote has expired or is disabled before then.
Collateral also requires a valid price. If your collateral cannot be priced when a taker reaches your book, that order reverts. Expired oracle prices on your collateral prevent quote fills.
Where to go next
| Goal | Page |
|---|---|
| Quote writes, the quote update loop, disabling quotes | Quoting |
| Account margin math | Collateral & margin |
| Funding rate and settlement | Funding |
| Liquidation waterfall and keepers | Liquidations |
| Maker rebates | Fees |
