Welcome to API Academy

Module 05 · API basics · ~25 min

Orders.

By the end of this module, your bot can actually place trades, open positions when its signal fires, scale them however your risk model dictates, and pull them back the moment the market turns. The point on the curriculum where it stops being a reader and starts being a trader.

To get there, you’ll place, size, and cancel real orders on Limitless, limit orders that rest on the book, FOK orders that cross it immediately, and the three cancel paths every bot needs when the market moves. Every trade your bot ever makes will flow through these endpoints.

API basics tier · Reference card
Quick answer

How do you place an order via the Limitless API?

Through the SDK’s OrderClient.createOrder(), which wraps POST /orders: it signs an EIP-712 payload with your wallet, attaches your API key, and submits the order. You need both LIMITLESS_API_KEY and PRIVATE_KEY set, plus the market slug, outcome token id, side, price, and size. Three order types cover everything: GTC (Good-Til-Cancelled) rests on the book at your price, FAK (Fill-And-Kill) matches immediately available liquidity and cancels the remainder, and FOK (Fill-Or-Kill) crosses the book for a fixed makerAmount of USDC, filling entirely or rejecting. The response carries an orderId and a settlementStatus (UNMATCHED is expected for a resting limit). Attach a clientOrderId so retries are idempotent, duplicates return 409 Conflict instead of a second fill, and remember the ack means “received,” not “filled.”

Order endpoints verified 2026-06-09 against the OpenAPI spec.

Section 01

Order types.

Two primitives: limit orders sit on the book at a price you choose, market orders cross the book immediately. Pick based on whether you care more about price or fill.

Limit orders

Post an order at a specific price and wait for a counterparty to cross it. You control the price; the exchange cannot fill you worse. You don’t control whether (or when) you fill.

  • Price certainty
  • Earns maker rebates when resting
  • Use for passive fills and market making
  • No fill guarantee

Market orders

Take the best available price on the book, whatever it is. You control the fill; the exchange controls the price. On a thin book, slippage can hurt.

  • Fill certainty (if depth exists)
  • Use when you need to get out fast
  • Use when crossing a signal
  • Always pass a max-slippage guard

Section 02

Placing a limit order.

The SDK’s OrderClient wraps POST /orders. Under the hood it signs an EIP-712 payload with your wallet, attaches your API key, and submits it. You pass the market slug, outcome token id, side, price, and size; the SDK handles the signing and submits a GTC order.

How to run this

  1. Set both LIMITLESS_API_KEY and PRIVATE_KEY in your environment. Swap btc-100k-weekly for a real market slug and pick a price that won’t cross the book immediately.
  2. Save as place-limit.ts, then run npx tsx place-limit.ts.
  3. You see an orderId and a settlementStatus printed, UNMATCHED is expected for a resting limit. Your order is live on the book.
// Module 05, Placing a Limit Order
// Buy 100 YES on a market at $0.42, good-til-cancelled.

import {
  HttpClient,
  MarketFetcher,
  OrderClient,
  Side,
  OrderType,
} from '@limitless-exchange/sdk';
import { Wallet } from 'ethers';

const httpClient    = new HttpClient({ apiKey: process.env.LIMITLESS_API_KEY });
const marketFetcher = new MarketFetcher(httpClient);
const wallet        = new Wallet(process.env.PRIVATE_KEY!);
const orderClient   = new OrderClient({ httpClient, wallet, marketFetcher });

async function placeLimit() {
  const market = await marketFetcher.getMarket('btc-100k-weekly');

  const result = await orderClient.createOrder({
    marketSlug: market.slug,
    tokenId:    market.positionIds[0],    // YES outcome token
    side:       Side.BUY,
    price:      0.42,                     // USDC per share, 0.01–0.99
    size:       100,                      // number of shares
    orderType:  OrderType.GTC,            // rests until cancelled
  });

  console.log('orderId:         ', result.order.id);
  console.log('settlementStatus:', result.execution.settlementStatus);
  // UNMATCHED | MATCHED | MINED | CONFIRMED | RETRYING | FAILED
}

placeLimit().catch(console.error);

Three order types: GTC, FAK, and FOK.

GTC (Good-Til-Cancelled) rests on the book at your price until it fills or you cancel. FAK (Fill-And-Kill) matches immediately available liquidity at your price/size and cancels any unmatched remainder, the partial-fill variant. FOK (Fill-Or-Kill) crosses the book immediately for a fixed makerAmount, it fills entirely or rejects.

Section 03

Placing a market order.

Limitless expresses “market” orders as OrderType.FOK, fill-or-kill. You commit a fixed makerAmount of USDC and the matching engine either fills the whole thing against the book or rejects the order entirely. No price, no slippage guessing, no partial fills.

// Module 05, Placing a Market Order (FOK)
// Spend $50 of USDC crossing the book for YES. Fill-or-kill.

import {
  HttpClient,
  MarketFetcher,
  OrderClient,
  Side,
  OrderType,
} from '@limitless-exchange/sdk';
import { Wallet } from 'ethers';
import { randomUUID } from 'node:crypto';

const httpClient    = new HttpClient({ apiKey: process.env.LIMITLESS_API_KEY });
const marketFetcher = new MarketFetcher(httpClient);
const wallet        = new Wallet(process.env.PRIVATE_KEY!);
const orderClient   = new OrderClient({ httpClient, wallet, marketFetcher });

async function placeMarket() {
  const market = await marketFetcher.getMarket('btc-100k-weekly');

  const result = await orderClient.createOrder({
    marketSlug:    market.slug,
    tokenId:       market.positionIds[0],
    side:          Side.BUY,
    makerAmount:   50,              // USDC budget, no price, no size
    orderType:     OrderType.FOK,
    clientOrderId: randomUUID(),    // idempotency, see Section 04
  });

  console.log('matched:          ', result.execution.matched);
  console.log('settlementStatus: ', result.execution.settlementStatus);
  console.log('usdNet:           ', result.execution.totalsRaw.usdNet);
  console.log('txHash:           ', result.execution.txHash);
}

placeMarket().catch(console.error);

How to run this

  1. Keep both env vars set. Check the orderbook first, FOK rejects partial fills, so pick a makerAmount the book can actually absorb.
  2. Save the snippet above as place-market.ts, then run npx tsx place-market.ts.
  3. On success you see matched: true, a settlement status, the USDC usdNet, and a txHash you can look up on Base.

FOK is atomic, size the makerAmount deliberately.

Because FOK rejects partial fills, a too-large makerAmount on a thin book will keep bouncing back. Check GET /markets/{slug}/orderbook first, or start with a GTC limit that crosses and let it rest if it doesn’t fill.

Section 04

Cancelling orders.

Cancel a single order by id, cancel every order on a market in one shot, or batch-cancel a specific set with POST /orders/cancel-batch. For idempotent order creation, attach a clientOrderId to the original createOrder call, duplicates return 409 Conflict instead of double-submitting.

// Module 05, Cancelling Orders
// Cancel one by id, cancel all on a market, or batch-cancel a set.

import {
  HttpClient,
  MarketFetcher,
  OrderClient,
} from '@limitless-exchange/sdk';
import { Wallet } from 'ethers';

const httpClient    = new HttpClient({ apiKey: process.env.LIMITLESS_API_KEY });
const marketFetcher = new MarketFetcher(httpClient);
const wallet        = new Wallet(process.env.PRIVATE_KEY!);
const orderClient   = new OrderClient({ httpClient, wallet, marketFetcher });

async function cancelEverything(orderId: string, marketSlug: string) {
  // 1. Cancel one order by id.
  //    DELETE /orders/{orderId}
  await orderClient.cancel(orderId);

  // 2. Cancel every live order on a single market.
  //    DELETE /orders/all/{slug}
  await orderClient.cancelAll(marketSlug);

  // 3. Batch-cancel a specific set (orders must all be from the same market).
  //    POST /orders/cancel-batch  body: { orderIds: UUID[] }
  await httpClient.post('/orders/cancel-batch', {
    orderIds: [
      'c24c5aa4-8d8e-4e68-9fd3-d9e5e9e4b0a1',
      '4a1e1c56-9a13-4e22-8e17-0b2f4c1d3e22',
    ],
  });
}

cancelEverything('c24c5aa4-8d8e-4e68-9fd3-d9e5e9e4b0a1', 'btc-100k-weekly')
  .catch(console.error);

How to run this

  1. Keep both env vars set. Replace the two example UUIDs with real orderId values from the limit order you placed in Section 02.
  2. Save the snippet above as cancel-orders.ts, then run npx tsx cancel-orders.ts.
  3. No errors thrown. The REST API returns 2xx on each cancel and your order disappears from the book when you re-query positions.

Wire orders into your control panel.

The seed fills.ndjson you dropped in Module 02 was hand-written. As soon as your code from this module places a real order and a fill comes back, append a line with the same shape (ts, market, side, size_usd, price, order_id) to $ACADEMY_DATA_DIR/fills.ndjson. The recent-fills feed in your panel surfaces the new line on the next poll, the moment your order placement code stops being abstract and shows up on your phone.

Common questions

Placing orders on Limitless: what people ask

Each answer also ships invisibly as schema.org FAQ data for search engines and AI assistants. Tap a question to expand.

  1. What is the difference between GTC, FAK, and FOK orders?
    GTC (Good-Til-Cancelled) rests on the book at your price until it fills or you cancel. FAK (Fill-And-Kill) matches immediately available liquidity at your price/size and cancels any unmatched remainder, the partial-fill variant. FOK (Fill-Or-Kill) crosses the book immediately for a fixed makerAmount of USDC: it fills entirely or rejects. GTC and FAK take price/size; FOK takes makerAmount.
  2. How do you place a market order on Limitless?
    Limitless expresses market orders as OrderType.FOK: you commit a fixed makerAmount of USDC and the matching engine fills the whole thing against the book or rejects the order entirely. No price, no slippage guessing, no partial fills. Because FOK is atomic, a too-large makerAmount on a thin book keeps bouncing back, so check GET /markets/{slug}/orderbook first, or start with a GTC limit that crosses and let it rest if it doesn’t fill.
  3. How do you cancel orders via the Limitless API?
    Three paths. Cancel one by id with DELETE /orders/{orderId} (orderClient.cancel). Cancel every live order on a single market with DELETE /orders/all/{slug} (cancelAll). Batch-cancel a specific set with POST /orders/cancel-batch and a body of orderIds; the batch must all be from the same market. Your bot needs all three for the moment a signal flips or the book moves against it.
  4. Does an order acknowledgment mean the order filled?
    No, they’re different events. placeOrder resolves with a txHash the moment the exchange accepts the order; a resting limit comes back UNMATCHED, and the matching engine can still bounce an order inside the spread. Move position state on fill events only: subscribe to order events, or poll POST /orders/status/batch with the order id until it shows filled.
  5. How do you make order placement idempotent?
    Attach a clientOrderId (a UUID) to the original createOrder call. If a retry resubmits the same order, the API returns 409 Conflict instead of double-submitting, so a network blip can’t turn one intended position into two. The module’s market-order example generates one with randomUUID(); treat it as mandatory on anything that crosses the book.

Section 05

Module checklist.

Tick each item once you’ve actually done it. The Continue button unlocks at 5/5.

Module 05 complete

Orders flowing.

Your bot is now a trader, not just an observer. It can open a position when a signal fires, size it however your risk model dictates, and unwind it the moment the trade stops working, without you watching the book.

Concretely, you can place orders on Limitless and pull them back when the market moves. Three things you walk away with:

01

A working OrderClient that signs EIP-712 orders for you, resting limits (GTC), market orders (FOK), and partial-fill crosses (FAK).

02

A clientOrderId pattern for idempotent submission, retries can’t double-spend, and duplicates return 409 Conflict instead of a second fill.

03

Three cancel paths, single by id, all-on-a-market, or a specific batch, so you can unwind fast when a signal flips or the book moves against you.

Next up: tracking what your bot actually holds. Module 06 covers positions, fills, and the PnL math that turns a stream of orders into a live P&L number you can stake decisions on.

Complete the checklist above to unlock