# Place Paper Order

> Buys or sells one side of a market on paper. Rivo fills the order against the venue's live order book at the venue's real fee.

Source: https://rivo.markets/docs/reference/place-paper-order

`POST /v2/paper-orders`

Scope: `write`

This route places one paper trade by hand. No money moves, and you do not need a venue account. Rivo prices the order against the venue's live order book and folds the venue's taker fee into the price. It records only what fills right now, and nothing rests on the book.

To name the side, set `market` to a contract's `ref` and `outcome` to the side's `name` or `label`. You can find all three under `outcomes[]` on [Get Market](https://rivo.markets/docs/reference/get-market). You can also pass `yes` or `no` as `outcome`. The order comes back with the side's `name`.

- A buy spends `usd`. A sell gives back `contracts`, or `"all"` to sell everything held by hand on that side.
- `maxPrice` on a buy, or `minPrice` on a sell, fills only the part of the book inside that price. If nothing inside that price can fill, the API refuses the order and records nothing.
- A sell closes only paper you bought by hand. It never touches a bot's holdings.

> **Retries:** Send an `Idempotency-Key` header and reuse it when you retry. The same key always names the same trade. A retry returns the first fill with `Idempotent-Replayed: true` and never places a second trade. If the API refuses an order, you can use its key again. See [Errors](https://rivo.markets/docs/errors#retrying-a-paper-order).

## Example request

curl:

```bash
curl -X POST "https://api.rivo.markets/v2/paper-orders" \
  -H "Authorization: Bearer rivo_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-2026-10-15-milwaukee-1" \
  -d '{
  "market": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
  "outcome": "Milwaukee",
  "action": "buy",
  "usd": 250,
  "maxPrice": 0.9
}'
```

Python:

```python
import requests

url = "https://api.rivo.markets/v2/paper-orders"
headers = {
    "Authorization": "Bearer rivo_live_...",
    "Idempotency-Key": "order-2026-10-15-milwaukee-1",
}
body = {
    "market": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
    "outcome": "Milwaukee",
    "action": "buy",
    "usd": 250,
    "maxPrice": 0.9,
}

res = requests.post(url, headers=headers, json=body)
res.raise_for_status()
print(res.json())
```

TypeScript:

```typescript
const res = await fetch("https://api.rivo.markets/v2/paper-orders", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RIVO_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "order-2026-10-15-milwaukee-1",
  },
  body: JSON.stringify({
    "market": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
    "outcome": "Milwaukee",
    "action": "buy",
    "usd": 250,
    "maxPrice": 0.9
  }),
});
if (!res.ok) throw new Error(`Rivo API ${res.status}`);
const { data } = await res.json();
```

## Headers

- `Idempotency-Key` (string, optional): An optional unique value for each order, up to 200 characters. Reuse it when you retry. Rivo keeps it for 24 hours.

## Body

- `market` (market ref, required): One contract's `ref`. The API refuses a market with several contracts, so use a `ref` from its `outcomes[]` instead.
- `outcome` (string, required): The side's `outcomes[].name` or `outcomes[].label`, or `yes` or `no`.
- `action` (string, required): Whether to buy or sell: `buy` or `sell`.
- `usd` (number, optional): The dollars to spend, above 0 and up to 1,000,000. Send it on a buy, where it is required.
- `contracts` (number or "all", optional): The number of contracts to sell, up to 10,000,000, or `"all"`. Send it on a sell, where it is required.
- `maxPrice` (number, optional): On a buy, the most to pay for each contract, between 0 and 1.
- `minPrice` (number, optional): On a sell, the least to accept for each contract, between 0 and 1.

## Example response

```json
{
  "data": {
    "id": "5b7e0c1a-2f4d-4c8e-9a61-3d2f7b9e0a14",
    "market": {
      "ref": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
      "contract": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
      "title": "Milwaukee wins",
      "venue": "kalshi",
      "category": "sports",
      "kind": "mlb"
    },
    "outcome": "Yes",
    "action": "buy",
    "contracts": 284,
    "avgPrice": 0.8796,
    "cost": 249.81,
    "unfilledContracts": 0,
    "filledAt": "2026-10-15T02:31:07.412Z"
  }
}
```

## Response fields

- `data` (object): The filled order.
  - `id` (string): The paper order's id.
  - `market` (object): The market this row is about.
    - `ref` (market ref): The market's ref. You can pass it to any `market` filter or to [Get Market](https://rivo.markets/docs/reference/get-market). On a market of several outcomes, it names the whole event.
    - `contract` (market ref or null): The ref of the exact contract. It is the same as `ref` on a market with one contract. On a market of several outcomes, such as a game with a moneyline and a spread, it tells the contracts apart. Pass it to [Place Paper Order](https://rivo.markets/docs/reference/place-paper-order) or a market bot.
    - `title` (string): The market's title, as the venue writes it.
    - `venue` (string): The venue that lists the market: one of `kalshi`, `polymarket`, `polymarket_us` or `gemini`.
    - `category` (string or null): The market's category: one of `sports`, `politics`, `crypto`, `finance`, `culture`. It is `null` when Rivo has not classified the market.
    - `kind` (string or null): The kind of market, such as `nfl` or `bitcoin`. It is `null` when Rivo has not classified the market yet.
  - `outcome` (string): The side traded, using the name that [Get Market](https://rivo.markets/docs/reference/get-market) gives it.
  - `action` (string): Whether the order bought or sold: `buy` or `sell`.
  - `contracts` (number): The number of contracts that filled.
  - `avgPrice` (number): The average price for each contract, from 0 to 1, with the venue's fee included.
  - `cost` (number): What the buy cost, or what the sale brought in, in USD with the fee included.
  - `unfilledContracts` (number): The contracts the book could not fill right away. Paper orders never rest on the book, so Rivo drops this part.
  - `filledAt` (string): When the order filled, in ISO 8601 UTC.

Paper holdings settle when the market settles. You can see them in [Get Paper Account](https://rivo.markets/docs/reference/get-paper-account).

## Errors

| Code | When |
| --- | --- |
| `SCOPE_REQUIRED` | The key does not have the `write` scope. |
| `VALIDATION` | A required field is missing, or you sent a field that does not fit the action. `market` names a market with several contracts, or `outcome` is not one of the market's sides. You hold nothing by hand to sell, or nothing in the book fills inside your price limit. Or you already used the `Idempotency-Key` for a different order. |
| `NOT_FOUND` | No market has that ref. |
| `IDEMPOTENCY_IN_PROGRESS` | Rivo is still placing an order with the same `Idempotency-Key`. Wait, then retry with the same key. |
