Create Bot
This route starts a paper bot. The trigger decides what kind of bot it is:
| trigger | Kind | What it does |
|---|---|---|
{ "trader": ref } | trader | The bot follows the trader and copies each of their buys on paper at your sizing. |
{ "signal": {...} } | signal | The bot copies every whale buy that matches the signal, at your sizing. It uses the same signal that Backtest scores. |
{ "market": ref, "outcome": name, "rule": {...} } | market | The bot watches one side of one contract and buys and sells by its rule. |
Every bot you make here trades on paper. Trader bots work only on venues that name their traders. An account can hold up to 20 signal bots and 20 market bots.
Market bot rules
Set at most one of buyBelow, buyAbove, dropsBy and risesBy. If you set none, the bot buys right away.
Example request
curl -X POST "https://api.rivo.markets/v2/bots" \
-H "Authorization: Bearer rivo_live_..." \
-H "Content-Type: application/json" \
-d '{
"trigger": {
"market": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
"outcome": "Milwaukee",
"rule": {
"buyBelow": 0.8,
"takeProfit": 0.95
}
},
"sizing": {
"usd": 100
}
}'import requests
url = "https://api.rivo.markets/v2/bots"
headers = {
"Authorization": "Bearer rivo_live_...",
}
body = {
"trigger": {
"market": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
"outcome": "Milwaukee",
"rule": {
"buyBelow": 0.8,
"takeProfit": 0.95,
},
},
"sizing": {
"usd": 100,
},
}
res = requests.post(url, headers=headers, json=body)
res.raise_for_status()
print(res.json())const res = await fetch("https://api.rivo.markets/v2/bots", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIVO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"trigger": {
"market": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
"outcome": "Milwaukee",
"rule": {
"buyBelow": 0.8,
"takeProfit": 0.95
}
},
"sizing": {
"usd": 100
}
}),
});
if (!res.ok) throw new Error(`Rivo API ${res.status}`);
const { data } = await res.json();Body
triggerobjectrequiredOne of the three forms above. The API refuses unknown fields.
Show 5 trigger fields
tradertrader refFor a trader bot, the trader to copy.
signalobjectFor a signal bot, the signal to run.
Show 9 signal fields
venuestring[]Matches buys on these venues:
kalshi,polymarket,polymarket_usorgemini. You can pass up to 50. Leave it out to match every venue.categorystring[]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.minUsdnumberThe smallest trade to match, in USD.
maxUsdnumberThe largest trade to match, in USD. It must be at least
minUsd.priceMinnumberThe lowest price paid to match, from 0 to 1.
priceMaxnumberThe highest price paid to match, from 0 to 1. It must be at least
priceMin.entrystringdefaultallWhich buys to match.
openmatches new positions only,addmatches buys that add to a position, andallmatches both.traderstrader ref[]Matches only these traders' buys. Pass 1 to 25 trader refs.
keywordsstring[]Matches markets whose name contains any of these words. Pass 1 to 10 words, each up to 40 characters.
marketmarket refFor a market bot, one contract's
ref. Take it fromoutcomes[].refon Get Market.outcomestringFor a market bot, the side to trade. Use
outcomes[].nameoroutcomes[].label, oryesorno.ruleobjectFor a market bot, when to buy and sell. Set at most one of
buyBelow,buyAbove,dropsByandrisesBy. If you set none, the bot buys right away.Show 10 rule fields
buyBelownumberThe bot buys when the side's price falls to this level, between 0 and 1.
buyAbovenumberThe bot buys when the side's price rises to this level, between 0 and 1.
dropsBynumberThe bot buys when the price drops this far below where it stood when the bot started. Write it in dollars of price, so
0.05is 5 points.risesBynumberThe bot buys when the price rises this far above where it stood when the bot started. Write it in dollars of price.
takeProfitnumberThe bot sells when the price reaches this level, between 0 and 1.
stopLossnumberThe bot sells when the price falls to this level, between 0 and 1.
takeProfitPointsnumberThe bot sells when the price rises this far above the price paid. Write it in dollars of price.
stopLossPointsnumberThe bot sells when the price falls this far below the price paid. Write it in dollars of price.
maxHoldHoursnumberThe bot sells after it has held the position this many hours, up to 720.
repeatbooleandefaultfalseSet to
trueto buy again after each sale. When it is off, the bot trades once, or once per market when it follows a series.
namestringThe bot's name, from 1 to 60 characters. Only signal bots take a name. If you leave it out, Rivo names the bot after its signal.
sizingobjectdefault{ "usd": 100 }How much each trade stakes. Send exactly one of the two forms below. A market bot takes
{ usd }only.Show 3 sizing fields
usdnumberA fixed stake for each trade in USD, above 0 and up to 1,000,000.
percentnumberStakes this percentage of the source trade's dollars, above 0 and up to 10,000. Send it together with
maxUsd.maxUsdnumberThe most any one trade stakes when you use
percent, in USD, up to 1,000,000.
mirrorExitsbooleandefaultfalseSet to
trueto make a trader bot sell when the trader sells. Only trader bots take it.seriesbooleanSet to
trueto move a market bot on to the next market of the repeating series after each one. Only market bots take it.alertsbooleandefaulttrueWhether the bot sends in-app and Telegram messages about its trades.
Example response
{
"data": {
"id": "market:7a0e4c92-13bd-4e61-8f2a-c5d9b0317e48",
"name": "Milwaukee wins",
"kind": "market",
"mode": "paper",
"summary": "Buy Yes when it falls to 80¢, sell at 95¢",
"status": "running",
"venues": ["kalshi"],
"profit": 0,
"winRate": null,
"lastTradeAt": null,
"settings": {
"market": {
"ref": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
"contract": "a2Fsc2hpOm1hcmtldDpLWE1MQkdBTUUtMjZPQ1QxNDIwMDBNSUxMQUQtTUlM",
"title": "Milwaukee wins",
"outcome": "Yes",
"series": false
},
"rule": { "buyBelow": 0.8, "takeProfit": 0.95, "repeat": false },
"sizing": { "usd": 100 },
"alerts": true
},
"record": {
"trades": 0,
"settled": 0,
"wins": 0,
"losses": 0,
"open": 0,
"winRate": null,
"realized": 0,
"unrealized": 0,
"profit": 0,
"staked": 0,
"return": null
},
"curve": []
}
}Response fields
dataobjectThe new bot, with the same fields Get Bot returns. The API answers with status
201 Created.Show 15 data fields
idstringThe bot's id:
trader:<id>,signal:<id>ormarket:<id>.namestringThe bot's name. A trader bot takes its trader's name, and a market bot takes the name of its market or series.
kindstringThe kind of bot. A
traderbot copies one trader, asignalbot runs a signal, and amarketbot runs a price rule on one market.modestringWhether the bot trades on
paperorlive. A live bot trades real money. You set it up in the app, and the API can only read it.summarystringWhat the bot does, in one line.
statusstringThe bot's status:
running,pausedorended. A signal bot is never paused. It runs for as long as it exists.venuesstring[]The venues the bot trades on.
profitnumberThe bot's profit in USD, from both closed and open trades.
winRatenumber or nullThe share of the bot's settled trades that won, from 0 to 1.
lastTradeAtstring or nullWhen the bot last traded, in ISO 8601 UTC.
settingsobjectWhat the bot runs. The response includes only the fields for the bot's kind.
Show 7 settings fields
traderobjectOn a trader bot, the trader it copies.
Show 2 trader fields
reftrader refThe trader's ref.
namestring or nullThe trader's public name.
signalobject or nullOn a signal bot, the signal, with the same fields Backtest takes. It is
nullwhen the bot holds settings that only the app can edit.marketobjectOn a market bot, the contract and side it watches.
Show 4 market fields
refmarket refThe contract's ref.
titlestringThe contract's title.
outcomestringThe side the bot trades:
YesorNo.seriesbooleanWhether the bot follows the repeating series.
ruleobjectOn a market bot, the rule, with the same fields
POST /v2/botstakes.sizingobject or nullHow much each trade stakes:
{ usd }or{ percent, maxUsd }.mirrorExitsbooleanOn a trader bot, whether it sells when the trader sells.
alertsbooleanWhether the bot sends in-app and Telegram messages.
recordobjectThe bot's record.
Show 11 record fields
tradesintegerThe number of trades the bot took.
settledintegerThe number of trades that settled or closed.
winsintegerThe number of wins.
lossesintegerThe number of losses.
openintegerThe number of trades still open.
winRatenumber or nullThe share of settled trades that won, from 0 to 1.
realizednumberThe profit from closed trades, in USD.
unrealizednumberThe profit on open trades, in USD.
profitnumberThe closed and open profit added together, in USD.
stakednumberThe dollars the bot staked.
returnnumber or nullThe profit divided by the dollars staked.
curveobject[]The running total of closed profit, one point for each trade.
Show 2 curve fields
timestringThe time of this point, in ISO 8601 UTC.
profitnumberThe total profit up to this point, in USD.
tradesobjectOne page of the bot's trades, newest first, when you ask for
include=trades.Show 2 trades fields
dataobject[]The trades on this page.
Show 10 data fields
marketobject or nullThe market the trade is on. Here
categoryandkindare alwaysnull.Show 6 market fields
refmarket refThe market's ref. You can pass it to any
marketfilter or to Get Market. On a market of several outcomes, it names the whole event.contractmarket ref or nullThe ref of the exact contract. It is the same as
refon 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 or a market bot.titlestringThe market's title, as the venue writes it.
venuestringThe venue that lists the market: one of
kalshi,polymarket,polymarket_usorgemini.categorystring or nullThe market's category: one of
sports,politics,crypto,finance,culture. It isnullwhen Rivo has not classified the market.kindstring or nullThe kind of market, such as
nflorbitcoin. It isnullwhen Rivo has not classified the market yet.
outcomestringThe side the bot bought.
contractsnumberThe number of contracts bought.
entryPricenumberThe price paid, from 0 to 1.
pricenumberThe price now while the trade is open. Once it closes, this is the exit price or the payout.
profitnumberThe profit in USD.
statusstringWhether the trade is
openorclosed.resultstring or nullThe result once the trade closes:
win,lossorvoid.openedAtstringWhen the trade opened, in ISO 8601 UTC.
closedAtstring or nullWhen the trade closed, in ISO 8601 UTC.
nextCursorstring or nullPass this as
cursorto read the next page. It isnullon the last page.
activityobject or nullHow busy the bot's trigger has been, when you ask for
include=activity. It isnullfor a market bot.Show 4 activity fields
tradesintegerThe number of trades the trigger matched in the window.
windowDaysintegerThe length of the window in days, which is 30.
medianTradeUsdnumber or nullThe middle trade size, in USD.
lastTradeAtstring or nullWhen the newest matching trade happened, in ISO 8601 UTC.
Errors
| Code | When |
|---|---|
SCOPE_REQUIRED | The key does not have the write scope. |
VALIDATION | A field is unknown, or you sent it for the wrong kind of bot: name on a trader or market bot, mirrorExits on a signal or market bot, or series on a trader or signal bot. The trader's venue does not name traders, or you already have a bot on this trader. A market bot's sizing is not { usd }, the market has several contracts, or the outcome is not one of its sides. Or the account already holds its limit of bots. |
NOT_FOUND | No trader or market has that ref. |