# Update Bot

> Changes a paper bot's sizing, signal, rule, alerts or status.

Source: https://rivo.markets/docs/reference/update-bot

`PATCH /v2/bots/{id}`

Scope: `write`

This route changes a paper bot. Send only the fields you want to change. Each kind of bot takes its own fields:

| Kind | Takes |
| --- | --- |
| trader | `sizing`, `mirrorExits`, `status`, `alerts` |
| signal | `name`, `signal`, `sizing`, `alerts` |
| market | `rule`, `sizing` (`{ usd }` only), `status`, `alerts` |

You cannot pause a signal bot. It records every match for as long as it exists, so delete it to stop it. Some signal bots hold settings that only the app can edit, such as sports leagues. Change those bots' signals in the app. The API refuses changes to a live bot.

## Example request

curl:

```bash
curl -X PATCH "https://api.rivo.markets/v2/bots/signal%3A2c91e7d4-5a3b-4f08-b6e2-91d04f7a3c55" \
  -H "Authorization: Bearer rivo_live_..." \
  -H "Content-Type: application/json" \
  -d '{
  "sizing": {
    "usd": 100
  },
  "alerts": true
}'
```

Python:

```python
import requests

url = "https://api.rivo.markets/v2/bots/signal%3A2c91e7d4-5a3b-4f08-b6e2-91d04f7a3c55"
headers = {
    "Authorization": "Bearer rivo_live_...",
}
body = {
    "sizing": {
        "usd": 100,
    },
    "alerts": True,
}

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

TypeScript:

```typescript
const res = await fetch("https://api.rivo.markets/v2/bots/signal%3A2c91e7d4-5a3b-4f08-b6e2-91d04f7a3c55", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.RIVO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "sizing": {
      "usd": 100
    },
    "alerts": true
  }),
});
if (!res.ok) throw new Error(`Rivo API ${res.status}`);
const { data } = await res.json();
```

## Path parameters

- `id` (string, required): The bot's id, as [List Bots](https://rivo.markets/docs/reference/list-bots) returns it: `trader:<id>`, `signal:<id>` or `market:<id>`.

## Body

- `name` (string, optional): A signal bot's new name, from 1 to 60 characters.
- `sizing` (object, optional): How much each trade stakes. Send exactly one of the two forms below.
  - `usd` (number, optional): A fixed stake for each trade in USD, above 0 and up to 1,000,000.
  - `percent` (number, optional): Stakes this percentage of the source trade's dollars, above 0 and up to 10,000. Send it together with `maxUsd`.
  - `maxUsd` (number, optional): The most any one trade stakes when you use `percent`, in USD, up to 1,000,000.
- `signal` (object, optional): A signal bot's new signal. It replaces the old one.
  - `venue` (string[], optional): Matches buys on these venues: `kalshi`, `polymarket`, `polymarket_us` or `gemini`. You can pass up to 50. Leave it out to match every venue.
  - `category` (string[], optional): Matches buys in these categories: `sports`, `politics`, `crypto`, `finance`, `culture`. You can pass up to 5. It matches the market's stored category, as saved signal bots do.
  - `minUsd` (number, optional): The smallest trade to match, in USD.
  - `maxUsd` (number, optional): The largest trade to match, in USD. It must be at least `minUsd`.
  - `priceMin` (number, optional): The lowest price paid to match, from 0 to 1.
  - `priceMax` (number, optional): The highest price paid to match, from 0 to 1. It must be at least `priceMin`.
  - `entry` (string, optional, default `all`): Which buys to match. `open` matches new positions only, `add` matches buys that add to a position, and `all` matches both.
  - `traders` (trader ref[], optional): Matches only these traders' buys. Pass 1 to 25 trader refs.
  - `keywords` (string[], optional): Matches markets whose name contains any of these words. Pass 1 to 10 words, each up to 40 characters.
- `rule` (object, optional): A market bot's new rule. It replaces the old one. Set at most one of `buyBelow`, `buyAbove`, `dropsBy` and `risesBy`. If you set none, the bot buys right away.
  - `buyBelow` (number, optional): The bot buys when the side's price falls to this level, between 0 and 1.
  - `buyAbove` (number, optional): The bot buys when the side's price rises to this level, between 0 and 1.
  - `dropsBy` (number, optional): The bot buys when the price drops this far below where it stood when the bot started. Write it in dollars of price, so `0.05` is 5 points.
  - `risesBy` (number, optional): The bot buys when the price rises this far above where it stood when the bot started. Write it in dollars of price.
  - `takeProfit` (number, optional): The bot sells when the price reaches this level, between 0 and 1.
  - `stopLoss` (number, optional): The bot sells when the price falls to this level, between 0 and 1.
  - `takeProfitPoints` (number, optional): The bot sells when the price rises this far above the price paid. Write it in dollars of price.
  - `stopLossPoints` (number, optional): The bot sells when the price falls this far below the price paid. Write it in dollars of price.
  - `maxHoldHours` (number, optional): The bot sells after it has held the position this many hours, up to 720.
  - `repeat` (boolean, optional, default `false`): Set to `true` to buy again after each sale. When it is off, the bot trades once, or once per market when it follows a series.
- `mirrorExits` (boolean, optional): Set to `true` to make a trader bot sell when the trader sells.
- `status` (string, optional): A trader or market bot's status: `running` or `paused`.
- `alerts` (boolean, optional): Whether the bot sends in-app and Telegram messages about its trades.

## Example response

```json
{
  "data": {
    "id": "signal:2c91e7d4-5a3b-4f08-b6e2-91d04f7a3c55",
    "name": "Kalshi sports buys, 30¢ to 70¢, $5,000 or more",
    "kind": "signal",
    "mode": "paper",
    "summary": "Kalshi sports buys, 30¢ to 70¢, $5,000 or more",
    "status": "running",
    "venues": ["kalshi"],
    "profit": 523.17,
    "winRate": 0.5521,
    "lastTradeAt": "2026-10-15T01:58:12.000Z",
    "settings": {
      "signal": {
        "entry": "all",
        "venue": ["kalshi"],
        "category": ["sports"],
        "minUsd": 5000,
        "priceMin": 0.3,
        "priceMax": 0.7
      },
      "sizing": { "usd": 100 },
      "alerts": true
    },
    "record": {
      "trades": 212,
      "settled": 192,
      "wins": 106,
      "losses": 86,
      "open": 20,
      "winRate": 0.5521,
      "realized": 498.6,
      "unrealized": 24.57,
      "profit": 523.17,
      "staked": 19200,
      "return": 0.026
    },
    "curve": [
      { "time": "2026-09-22T19:04:51.000Z", "profit": -100 },
      { "time": "2026-09-23T01:12:08.000Z", "profit": 21.43 }
    ]
  }
}
```

## Response fields

- `data` (object): The bot after the change, with the same fields [Get Bot](https://rivo.markets/docs/reference/get-bot) returns.
  - `id` (string): The bot's id: `trader:<id>`, `signal:<id>` or `market:<id>`.
  - `name` (string): The bot's name. A trader bot takes its trader's name, and a market bot takes the name of its market or series.
  - `kind` (string): The kind of bot. A `trader` bot copies one trader, a `signal` bot runs a signal, and a `market` bot runs a price rule on one market.
  - `mode` (string): Whether the bot trades on `paper` or `live`. A live bot trades real money. You set it up in the app, and the API can only read it.
  - `summary` (string): What the bot does, in one line.
  - `status` (string): The bot's status: `running`, `paused` or `ended`. A signal bot is never paused. It runs for as long as it exists.
  - `venues` (string[]): The venues the bot trades on.
  - `profit` (number): The bot's profit in USD, from both closed and open trades.
  - `winRate` (number or null): The share of the bot's settled trades that won, from 0 to 1.
  - `lastTradeAt` (string or null): When the bot last traded, in ISO 8601 UTC.
  - `settings` (object): What the bot runs. The response includes only the fields for the bot's kind.
    - `trader` (object): On a trader bot, the trader it copies.
      - `ref` (trader ref): The trader's ref.
      - `name` (string or null): The trader's public name.
    - `signal` (object or null): On a signal bot, the signal, with the same fields [Backtest](https://rivo.markets/docs/reference/backtest) takes. It is `null` when the bot holds settings that only the app can edit.
    - `market` (object): On a market bot, the contract and side it watches.
      - `ref` (market ref): The contract's ref.
      - `title` (string): The contract's title.
      - `outcome` (string): The side the bot trades: `Yes` or `No`.
      - `series` (boolean): Whether the bot follows the repeating series.
    - `rule` (object): On a market bot, the rule, with the same fields `POST /v2/bots` takes.
    - `sizing` (object or null): How much each trade stakes: `{ usd }` or `{ percent, maxUsd }`.
    - `mirrorExits` (boolean): On a trader bot, whether it sells when the trader sells.
    - `alerts` (boolean): Whether the bot sends in-app and Telegram messages.
  - `record` (object): The bot's record.
    - `trades` (integer): The number of trades the bot took.
    - `settled` (integer): The number of trades that settled or closed.
    - `wins` (integer): The number of wins.
    - `losses` (integer): The number of losses.
    - `open` (integer): The number of trades still open.
    - `winRate` (number or null): The share of settled trades that won, from 0 to 1.
    - `realized` (number): The profit from closed trades, in USD.
    - `unrealized` (number): The profit on open trades, in USD.
    - `profit` (number): The closed and open profit added together, in USD.
    - `staked` (number): The dollars the bot staked.
    - `return` (number or null): The profit divided by the dollars staked.
  - `curve` (object[]): The running total of closed profit, one point for each trade.
    - `time` (string): The time of this point, in ISO 8601 UTC.
    - `profit` (number): The total profit up to this point, in USD.
  - `trades` (object): One page of the bot's trades, newest first, when you ask for `include=trades`.
    - `data` (object[]): The trades on this page.
      - `market` (object or null): The market the trade is on. Here `category` and `kind` are always `null`.
        - `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 the bot bought.
      - `contracts` (number): The number of contracts bought.
      - `entryPrice` (number): The price paid, from 0 to 1.
      - `price` (number): The price now while the trade is open. Once it closes, this is the exit price or the payout.
      - `profit` (number): The profit in USD.
      - `status` (string): Whether the trade is `open` or `closed`.
      - `result` (string or null): The result once the trade closes: `win`, `loss` or `void`.
      - `openedAt` (string): When the trade opened, in ISO 8601 UTC.
      - `closedAt` (string or null): When the trade closed, in ISO 8601 UTC.
    - `nextCursor` (string or null): Pass this as `cursor` to read the next page. It is `null` on the last page.
  - `activity` (object or null): How busy the bot's trigger has been, when you ask for `include=activity`. It is `null` for a market bot.
    - `trades` (integer): The number of trades the trigger matched in the window.
    - `windowDays` (integer): The length of the window in days, which is 30.
    - `medianTradeUsd` (number or null): The middle trade size, in USD.
    - `lastTradeAt` (string or null): When the newest matching trade happened, in ISO 8601 UTC.

## Errors

| Code | When |
| --- | --- |
| `SCOPE_REQUIRED` | The key does not have the `write` scope. |
| `NOT_FOUND` | No bot has that id. |
| `VALIDATION` | The body is empty, or a field is unknown or does not fit this kind of bot. You sent `status` to a signal bot, or a market bot's `sizing` is not `{ usd }`. The bot holds a signal that only the app can edit, or the bot is live. |
