---
title: "Place a spot order (market / limit / stop)"
method: POST
path: "/api/agent/spot/order"
tags: ["spot"]
---

# Place a spot order (market / limit / stop)

`POST /api/agent/spot/order`

## Request

- Base URL: `https://api.coinrithm.com`
- URL: `https://api.coinrithm.com/api/agent/spot/order`
- Auth: HTTP bearer

Paper spot order on your mock wallet. `coinId` is the coin UCID (NOT a
ticker symbol). `limitPrice` is required for limit/stop; `stopPrice` is
required for stop. Requires scope `trade:spot`.

`idempotencyKey` is REQUIRED for API-key callers and unique per intent:
reusing it replays the ORIGINAL result with `idempotentReplay: true`
(safe to retry a timed-out request with the same key — it will never
double-execute). The key follows the order across its lifecycle, so a
replay still resolves after a resting order fills or is cancelled.

## Request body

- SpotOrderRequest
  - `coinId` string, required: Coin UCID (e.g. "1" = BTC). NOT a ticker symbol.
  - `side` 'buy' | 'sell', required
  - `orderType` 'market' | 'limit' | 'stop', required
  - `quantity` number, required: Amount of the base coin (must be > 0).
  - `limitPrice` number: Required for limit/stop orders (USD per coin).
  - `stopPrice` number: Required for stop orders (USD trigger price).
  - `idempotencyKey` string, required: REQUIRED for API-key (agent) callers. Unique per intent; reusing it replays the original result (`idempotentReplay: true`) instead of double-executing — retry a timed-out request with the SAME key.
  - `agentTrace` AgentTraceMetadata: Optional private trace metadata supplied by a user-run agent. CoinRithm stores only this structured summary; do not send chain-of-thought, secrets, emails, or private account identity.
    - `runId` string, nullable
    - `decisionId` string, nullable
    - `strategyLabel` string, nullable
    - `confidence` number, nullable
    - `rationaleSummary` string, nullable

## Response `200`

Order accepted. For `market`, returns an execution summary; for
`limit`/`stop`, returns the resting-order summary.

- SpotOrderResponse: For a market order, `summary` carries execution details; for limit/stop, it carries the resting-order terms.
  - `message` string
  - `orderId` integer: Market fills (and their idempotent replays) only: the immutable ClosedOrder id of this fill, the same id `/api/agent/trades` lists for the spot row. It correlates the response with the ledger; it does not prove the fill used a particular quote. Limit/stop placement responses carry no order id; list resting orders with `/api/agent/orders/open`.
  - `summary` object
    - `side` string
    - `quantity` number
    - `executionPrice` number: market only; fill price after spread+slippage
    - `totalCost` number: market only
    - `pnl` number, nullable: market only; realized PnL in USD, net of fee. null on buys
    - `feeUsd` number, nullable: market only; taker fee charged on this fill
    - `slippageUsd` number, nullable: market only; modeled slippage cost
    - `executionModel` ExecutionModel: Paper Execution Realism v1 cost disclosure. Paper fills apply a deterministic, fully-disclosed cost so simulated PnL reflects real trading friction (a flat round-trip is a small loss, not a free breakeven). This is a rehearsal cost model, NOT an exchange fill guarantee. Per venue: - spot: a taker fee (`feeBps`) on notional, with market orders also filling at an adverse price (half-spread + slippage). Futures use the default-off legacy mark fill unless `futures_fill_v1` is pinned; that model applies deterministic half-spread, slippage, and square-root size-scaled impact, with adverse cost embedded in the executed price. - PM: fills at the ask (mid + half the ingested bid-ask spread) with size/liquidity-based slippage and a Polymarket-shaped taker fee (~1.8% near 50%, ~0 at the extremes), folded into `sharesMusd`. `feeBps`/`spreadBps` are positive and `slippageBps` scales with order size; `entryProbability` stays the mid for calibration. Futures quote funding is estimated from the latest venue rate when available and may change before settlement. Covered futures charges are applied from recorded settled venue history; `fundingMode` is a venue-specific mode such as `binance_perp_rate_v1`, `bybit_perp_rate_v1`, or `gateio_perp_rate_v1`, and is `not_modeled` when no latest rate is available. Funding does not apply to spot or PM. Futures liquidation forfeits margin without adverse fill cost, and fixed-price SL/TP triggers fill at their set price. Order-book depth, latency, and partial fills are not modeled.
      - `version` string
      - `feeBps` number: taker fee, basis points of notional
      - `spreadBps` number: modeled bid/ask spread (bps)
      - `slippageBps` number: modeled slippage (bps)
      - `fillModel` string, nullable: Futures fill model pinned for this execution, or null for legacy mark fills.
      - `estimatedFeeMusd` number: estimated fee for this trade (mUSD)
      - `estimatedSlippageMusd` number: estimated slippage cost for this trade (mUSD)
      - `fundingMode` string: Venue-specific current funding reference mode, or not_modeled when no latest rate is available.
      - `assumptions` string[]: human-readable list of what is and isn't modeled
    - `executionModelStatus` 'historical_parameters_not_retained': Market idempotent replay only.
    - `executionVersion` string, nullable: Market idempotent replay only. The fill's execution version, e.g. "paper_execution_v1"; null for a pre-realism fill.
    - `limitPrice` number: limit/stop only
    - `orderType` string: limit/stop only
  - `idempotentReplay` boolean: present (true) when this is a replay of a prior intent

## Other responses

- `400`: Rejected. `blockReasons` carries stable machine-readable codes from the same vocabulary as `spotQuote` (e.g. `price_unavailable`, `insufficient_usdt_balance`, `insufficient_coin_balance`) — same envelope shape as futures/PM entry blocks.
- `401`: Missing/malformed or invalid/revoked API key
- `403`: API key missing the required scope
- `404`: No active mock wallet (`blockReasons: ["wallet_not_found"]`).
- `409`: idempotencyKey already used (by a different intent/user), or `hosted_agent_not_active` when the owner paused this hosted agent
- `429`: Rate limit exceeded for this API key (120 req/min baseline, 20 trade-writes/min). Honor `Retry-After`, then resume; the `RateLimit-*` headers on every response let you pace proactively. (The platform also runs a per-IP limiter; its 429 body is `{"error": "rate_limited", "message": "..."}`.)
- `500`: Server error

---

[API](https://skmtc.dev/coinrithm/apis/coinrithm-agent-trading-api.md) · [All operations](https://skmtc.dev/coinrithm/apis/coinrithm-agent-trading-api/llms.txt) · [OpenAPI document](https://skmtc.dev/coinrithm/apis/coinrithm-agent-trading-api/revisions/28fb59f285fe?raw)
