Skip to main content
Every new order is checked in the same transaction that places it. A refused order creates nothing, and D1 never changes the quantity you asked for to make an order fit.

Trading availability

Having a key with mm:trade does not by itself mean you can place orders. A new order is accepted only when all of these hold:
  • the key is active, carries mm:trade, and was issued by D1 as a trading key;
  • your account is active, not suspended;
  • D1 has enabled trading for your account;
  • trading through the Market Maker API is switched on at D1.
D1 enables trading for an account during onboarding. Enabling it requires, among other checks, an available USDC balance of at least a minimum set by D1. Ask D1 for the current figure.

What you see when trading is unavailable

GET /mm/v1/status tells you whether a new order would be accepted right now:
A placement in that state is refused:
Even while trading is unavailable you can still:
  • read everything with mm:read, unless your account is suspended;
  • cancel and cancel-all;
  • retry an earlier placement with the same clientOrderId and get the existing order back.
Availability can change at any time, so treat TRADING_DISABLED as a normal state. Stop placing, cancel your resting orders if your strategy needs that, keep reconciling, and poll GET /mm/v1/status until trading.available is true again.

Sell-to-close

External MM V1 does not support option writing. You can never create or increase a net short position through this API.
  • BUY acquires a long position. It is limited only by your funds and order limits.
  • SELL is sell-to-close. You can sell only contracts you hold long and have not already committed to another resting SELL.
When you place a SELL, D1 sets aside that quantity of your long position for the order. That quantity cannot back a second SELL until the order fills or is cancelled.
The refusal looks like this:
D1 checks this when the order is placed and again on every fill, in the transaction that executes it. A fill can never take your position in a market below zero. To calculate how much you can still sell in a market, take your long quantity from GET /mm/v1/positions and subtract the remainingQuantity of your resting SELL orders in that market. GET /mm/v1/status reports this rule as trading.sellPolicy: "CLOSE_ONLY" and capabilities.writeOptions: false.

Funds

A BUY sets aside its full premium at the limit price from your available USDC: price × quantity, or price × quantity × contractSize for markets quoted per underlying unit. If your available balance does not cover it, the order is refused with 422 INSUFFICIENT_FUNDS. The amount set aside appears in reserved in GET /mm/v1/balances. It is paid out as the order fills, and whatever is left is released when the order is filled or cancelled. A SELL does not set aside USDC.

Order limits

Each account has three limits on its resting orders. GET /mm/v1/status returns the values that apply to you under limits:
An order that would break a limit is refused, and the body names the limit:
Read the limits from GET /mm/v1/status instead of hard-coding them. D1 may change them, and maxOpenExposure is null if no exposure limit is configured, in which case new orders are refused with TRADING_DISABLED.

What open-order exposure means

Open-order exposure is the premium your resting orders would trade if they all filled at their own limit prices. It counts both sides and every market:
For example, with QUOTE_PER_CONTRACT markets:
When you place an order, D1 adds the new order’s full quantity at its limit price, before any matching, and refuses it if the total would exceed maxOpenExposure. This applies even if the order would fill immediately. The same before-matching rule applies to the order counts: a new order needs room to rest, even if it would fill at once. Exposure goes down when orders fill or are cancelled. It is based only on your order prices. It is not a measure of your position value, margin or P&L.