Polymarket Order Types (2026): GTC, GTD, FOK and FAK Explained

The Short Answer
Polymarket supports four order types, set in the orderType field: GTC (Good Till Cancelled) and GTD (Good Till Date) for limit orders that can rest on the book, and FOK (Fill or Kill) and FAK (Fill and Kill) for orders that must execute immediately. Post-only is a separate flag, postOnly: true, that works with GTC and GTD only. In the unified TypeScript SDK, placeLimitOrder() creates a GTC order, adding an expiration turns it into GTD, and placeMarketOrder() defaults to FAK. A GTD order expires one minute before its stated time, and that time must be at least three minutes in the future.
Key Takeaways
- Every Polymarket order is a limit order. A market order is a limit order priced to match resting orders immediately.
- GTC rests until it fills or you cancel it. GTD expires 60 seconds before its
expiration, which must be at least 3 minutes away. - FOK fills the whole order or nothing, while FAK fills what it can and cancels the rest.
- Post-only orders are rejected instead of taking liquidity, and the API accepts them only as GTC or GTD.
- In the CLOB API,
orderTypeandpostOnlysit at the top level of thePOST /orderbody, outside the signed order.
What order types does Polymarket support?
| Order type | Name | What happens to the unfilled amount | Rests on the book? |
|---|---|---|---|
GTC | Good Till Cancelled | Stays open until it fills or you cancel it | Yes |
GTD | Good Till Date | Stays open until its expiration | Yes |
FOK | Fill or Kill | The whole order fills immediately, or none of it does | No |
FAK | Fill and Kill | Fills what is available now, and the rest is canceled | No |
Polymarket's documentation is blunt: "All orders on Polymarket are limit orders." A market order is a limit order priced to execute against the best resting orders, so the four types form two pairs. GTC and GTD decide how long an unfilled limit order stays open, and FOK and FAK decide what happens when an immediate order cannot fill completely. Post-only is a flag on a GTC or GTD order, not a fifth type.
How do limit and market orders behave on Polymarket?
A limit order names a price. If it crosses the spread, a buy at or above the lowest ask or a sell at or below the highest bid, it matches at once, and price improvement goes to the taker: a buy at $0.55 that meets a resting sell at $0.52 pays $0.52. Whatever does not fill stays open as GTC or GTD.
A market order takes its price from the current book and never rests, because "any amount that cannot fill is canceled." In the SDK, a market BUY takes amount in dollars and a SELL takes shares. maxPrice caps what a buy pays, minPrice floors what a sell accepts, and maxSpend sets an estimated all-in spend target that includes fees, which are otherwise charged on top.
| Setting | TypeScript SDK | Python SDK | CLOB API |
|---|---|---|---|
| Time in force | orderType: OrderType.FOK | order_type="FOK" | "orderType": "FOK" |
| GTD expiration | expiration | expiration | order.expiration |
| Post-only | postOnly: true | post_only=True | "postOnly": true |
| Price protection | maxPrice, minPrice | max_price, min_price | Set by the signed amounts |
How does a GTD order's expiration work?
expiration is a Unix timestamp in seconds. GTC orders send "0", and so do FOK and FAK orders, because neither rests. A GTD order carries the time it should end, under two rules from Polymarket's docs:
- It expires early. GTD orders "expire one minute before their stated expiration as a security threshold." For an effective lifetime of N seconds, set
expirationto now plus 60 plus N. - It needs a minimum runway. The expiration must be at least 3 minutes in the future, which makes the shortest effective lifetime about two minutes.
The SDK enforces the second rule before it signs anything, with the error "Expiration must be at least 3 minutes in the future." Over the raw API, the CLOB rejects orders that expire too soon, and its invalid expiration error covers timestamps that are in the past or invalid. This places a 30-minute post-only GTD bid with @polymarket/client 0.12.0, the latest release on 3 October 2026:
import { createSecureClient, OrderResponseErrorCode, OrderSide } from '@polymarket/client';
import { privateKey } from '@polymarket/client/viem';
const client = await createSecureClient({
signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY as `0x${string}`),
});
const market = await client.fetchMarket({ slug: 'your-market-slug' });
const assetId = market.outcomes.yes.tokenId!;
// Effective lifetime of 30 minutes, plus the 60-second security threshold
const expiration = Math.floor(Date.now() / 1000) + 60 + 30 * 60;
const response = await client.placeLimitOrder({
assetId,
side: OrderSide.BUY,
price: '0.52',
size: '10',
expiration,
postOnly: true,
});
if (response.ok) {
console.log(response.orderId, response.status);
} else if (response.code === OrderResponseErrorCode.POST_ONLY_WOULD_CROSS) {
console.log('This price would take liquidity, so quote further from the ask.');
} else {
console.error(response.code, response.message);
}
Leave out expiration and the same call places a GTC order. The SDK names the asset assetId, and the older tokenId parameter still works but is deprecated. On a rejection, response.code is a typed reason such as post_only_would_cross, so you can branch on it instead of parsing messages. Client setup is covered in the Polymarket SDK guide.
When should you use FOK or FAK?
Use FAK when a partial fill is acceptable, and FOK when the order only makes sense at full size, such as one leg of a two-sided trade. FAK still needs at least one match. If nothing on the book meets your price limit, the CLOB rejects it with "no orders found to match with FAK order." FOK rejects the whole order with "order couldn't be fully filled" when depth runs out.
One SDK detail catches people. placeMarketOrder() defaults to FAK, but estimateMarketPrice() models FOK unless told otherwise, and an FOK estimate throws when the book is too thin for the full amount. Pass the same orderType to both:
import { createSecureClient, OrderSide, OrderType } from '@polymarket/client';
import { privateKey } from '@polymarket/client/viem';
const client = await createSecureClient({
signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY as `0x${string}`),
});
const assetId = 'YOUR_TOKEN_ID';
const maxPrice = await client.estimateMarketPrice({
assetId,
side: OrderSide.BUY,
amount: '25',
orderType: OrderType.FOK,
});
const response = await client.placeMarketOrder({
assetId,
side: OrderSide.BUY,
amount: '25',
maxPrice,
orderType: OrderType.FOK,
});
console.log(response.ok ? response.status : `${response.code}: ${response.message}`);
The estimate is a snapshot, so the book can move before the order lands. Passing it as maxPrice turns a moved book into a rejection instead of a worse fill. Trading involves risk: in a thin book, a market buy walks up the asks, so its average price can land well above the best quote.
Does Polymarket support post-only orders?
Yes. Polymarket added post-only orders in January 2026. Set postOnly: true on a GTC or GTD order, and it either rests on the book as a maker order or is rejected with "invalid post-only order: order crosses book." The API schema says post-only is "only supported for GTC and GTD orders," and the SDK throws before it submits a post-only FOK or FAK order.
Post-only also matters during maintenance. While the matching engine restarts, order requests return HTTP 425, and for two minutes after it returns, only cancels and post-only orders are accepted. Any other new order gets HTTP 503 with "code": "post_only_mode" and a retry delay in retry_after_seconds and the Retry-After header.
How do you set the order type in the CLOB API?
Over raw HTTP, an order is a signed EIP-712 struct inside a JSON body sent to POST https://clob.polymarket.com/order with the five L2 headers. The time in force is not part of the signature: orderType and postOnly are top-level fields, and expiration travels in the order object but sits outside the signed CLOB V2 struct.
| Field | Where it goes | Values |
|---|---|---|
orderType | Top level | GTC (the default), GTD, FOK or FAK |
postOnly | Top level | true or false (the default), GTC and GTD only |
order.expiration | Order object | Unix seconds as a string, "0" unless the order is GTD |
deferExec | Top level | Polymarket's examples and the SDK send false |
A post-only GTD order body looks like this, with your signed values in place of the placeholders:
{
"deferExec": false,
"order": {
"builder": "0x0000000000000000000000000000000000000000000000000000000000000000",
"expiration": "YOUR_UNIX_SECONDS",
"maker": "YOUR_DEPOSIT_WALLET_ADDRESS",
"makerAmount": "5200000",
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
"salt": 479249096354,
"side": "BUY",
"signature": "YOUR_ORDER_SIGNATURE",
"signatureType": 3,
"signer": "YOUR_DEPOSIT_WALLET_ADDRESS",
"takerAmount": "10000000",
"timestamp": "YOUR_UNIX_MILLISECONDS",
"tokenId": "YOUR_TOKEN_ID"
},
"orderType": "GTD",
"owner": "YOUR_API_KEY",
"postOnly": true
}
makerAmount and takerAmount are six-decimal integers, so this BUY spends 5.20 USD for 10 shares at $0.52. signatureType 3 is a Deposit Wallet, where the maker and signer are both the wallet address. Batches go to POST /orders, which takes 1 to 15 of these entries, each with its own orderType. Check every result in the response, because one order can be accepted while another is rejected. Signing and the L2 headers are covered in the Polymarket CLOB API guide.
What do Polymarket order statuses mean?
| Status | Meaning |
|---|---|
live | The order is resting on the book |
matched | The order matched immediately with resting liquidity |
delayed | The order is marketable but waiting out a matching delay |
unmatched | A marketable order placed on the book after the delay expired without a match |
delayed comes from markets that hold marketable orders briefly: a taker delay on selected crypto and finance Up or Down markets, and a configured delay on some sports markets. The order is pending and cannot be canceled during the delay, and it is rejected if balance, allowance or risk checks fail when the delay ends. The unified SDK reports a raw unmatched status as ok: false with the code unmatched, so check open orders before resubmitting.
In our checks on 3 October 2026, Bitcoin 5-minute and 15-minute Up or Down markets returned itode: true, Polymarket's taker delay flag, from the public GET /clob-markets/{condition_id} endpoint, and soccer and esports markets reported secondsDelay: 1 in the Gamma API.
Why was my Polymarket order rejected?
| CLOB message | SDK code | Fix |
|---|---|---|
order couldn't be fully filled. FOK orders are fully filled or killed. | fok_not_filled | Cut the size, raise the limit or switch to FAK |
no orders found to match with FAK order | fak_not_filled | Nothing met your price limit, so re-estimate |
invalid post-only order: order crosses book | post_only_would_cross | Move the price off the opposite side |
invalid expiration | invalid_expiration | Set a GTD expiration at least 3 minutes ahead |
post-only mode: only post-only orders and cancels are allowed | post_only_mode | Wait out the retry delay or send post-only |
not enough balance / allowance | insufficient_balance_or_allowance | Add pUSD or set trading approvals |
the market is not yet ready to process new orders | market_not_ready | Wait, then retry |
Price (...) breaks minimum tick size rule | None | Round the price onto the tick grid |
Size (...) lower than the minimum | None | Meet the market's min_order_size |
In the 0.12.0 source, tick and size errors have no dedicated SDK code and arrive as unknown with the original message, though the SDK checks the tick grid before signing. Rounding onto it is covered in the Polymarket tick size guide. An order timed out error, an HTTP 500 during bursts of orders from one account, never reached the book, and Polymarket says it can be safely resubmitted.
How do you place orders across venues?
Order vocabularies differ from venue to venue, so a bot that trades beyond Polymarket ends up maintaining several sets of rules. The Predictefy API builds orders server side across 15+ venues through one integration, and you sign each one in your own wallet or process, so Predictefy never holds your funds or keys. To rehearse an order flow before real money is involved, paper trading costs 0 credits on every plan.
Frequently Asked Questions
What order types does Polymarket support?
Four: GTC (Good Till Cancelled) and GTD (Good Till Date) for limit orders that can rest on the book, and FOK (Fill or Kill) and FAK (Fill and Kill) for orders that execute immediately. Post-only is a separate flag available on GTC and GTD orders.
What is the difference between FOK and FAK on Polymarket?
FOK fills the entire order immediately or cancels all of it. FAK fills whatever liquidity meets your price limit and cancels the rest, but it is rejected if nothing matches at all. The unified SDK uses FAK by default for market orders.
How long does a GTD order last on Polymarket?
Until one minute before its expiration timestamp, which Polymarket applies as a security threshold. The expiration must be at least three minutes in the future, so set it to the current time plus 60 seconds plus the lifetime you want.
Does Polymarket support post-only orders?
Yes. Set postOnly to true on a GTC or GTD order. If it would match immediately, the CLOB rejects it with "invalid post-only order: order crosses book" instead of filling it as a taker.
Does Polymarket have market orders?
Yes, although every Polymarket order is a limit order underneath. A market order is priced from the current book so it matches immediately, uses FOK or FAK, and never rests on the book.
Why does my Polymarket order say delayed?
The market applies a matching delay to marketable orders, such as the taker delay on some crypto Up or Down markets or the configured delay on sports markets. The order cannot be canceled during the delay, and it is matched, placed on the book or rejected when the delay ends.