---
title: "Open a paper position"
method: POST
path: "/api/bot/v1/open"
tags: ["Paper trading"]
---

# Open a paper position

`POST /api/bot/v1/open`

## Request

- Base URL: `https://marginpad.io`
- URL: `https://marginpad.io/api/bot/v1/open`
- Auth: API key in header `X-API-Key`

Open a simulated position at the live price. Auth: header X-API-Key (mint one at POST /api/bot/key while signed in). Send client_order_id so a network retry cannot open a second position.

## Request body

- OpenRequest
  - `fee_venue` string, nullable: Charge this open at a real venue’s taker schedule less our referral discount (GET /v1/fees). Omit for your account default; null or "marginpad" for the default rate.
  - `symbol` string, required
  - `side` 'long' | 'short', required
  - `margin_usd` number, required
  - `leverage` number, required
  - `type` 'market' | 'limit': market fills now at the live price; limit rests until the market reaches limit_price and fills AT that price.
  - `limit_price` number: Required for type:"limit". The level may sit on EITHER side of the market: below it the order behaves as a classic limit, above it as a breakout entry. Either way it waits until the market reaches the level and fills AT the level.
  - `sl` number, nullable
  - `tp` number, nullable
  - `client_order_id` string: Idempotency key. Retrying with the same value returns the position the first call created (idempotent: true) instead of opening a second one. Strongly recommended.

## Response `200`

ok

- object
  - `ok` boolean
  - `position` Position
    - `id` string, required: Pass to /close and /sltp.
    - `symbol` string, required
    - `side` 'long' | 'short', required
    - `entry_price` number, required
    - `margin_usd` number, required
    - `leverage` number, required
    - `qty` number, required
    - `liq_price` number
    - `sl` number, nullable
    - `tp` number, nullable
    - `status` 'open' | 'closed' | 'liquidated', required
    - `opened_ts` integer
    - `source` 'bot' | 'app'
    - `mark_price` number: Open positions only.
    - `unrealized_pnl_usd` number: Open positions only. NET of the round-trip fee and accrued funding - what the position actually settles at, not a gross figure.
    - `fees_usd` number: Round-trip taker fee already subtracted from unrealized_pnl_usd.
    - `funding_usd` number: Funding accrued so far, already subtracted.
    - `exit_price` number, nullable: Closed positions only.
    - `pnl_usd` number, nullable: Closed positions only. Net of fees and funding, floored at -margin_usd.
    - `closed_ts` integer, nullable
    - `partial_pct` integer: Present when this row is a partial close.
  - `idempotent` boolean: true when this returned an existing position because client_order_id was reused.

## Other responses

- `400`: validation error
- `409`: too many open positions (Free 50 / API Pro 200 / Max 500 / Business 1000)
- `429`: rate limited - see X-RateLimit-Reset and Retry-After

---

[API](https://skmtc.dev/marginpad/apis/marginpad-free-crypto-api.md) · [All operations](https://skmtc.dev/marginpad/apis/marginpad-free-crypto-api/llms.txt) · [OpenAPI document](https://skmtc.dev/marginpad/apis/marginpad-free-crypto-api/revisions/27d21fcd0bf0?raw)
