curl --request POST \
--url https://arena-predictions.com/api/v1/portfolio/orders \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"action": "buy",
"type": "limit",
"instrumentId": "ins_0123456789AB",
"side": "yes",
"count": 10,
"limitPriceCents": 40,
"timeInForce": "gtc",
"idempotencyKey": "1b4e28ba-2fa1-41d2-883f-0016d3cca427"
}
'import requests
url = "https://arena-predictions.com/api/v1/portfolio/orders"
payload = {
"action": "buy",
"type": "limit",
"instrumentId": "ins_0123456789AB",
"side": "yes",
"count": 10,
"limitPriceCents": 40,
"timeInForce": "gtc",
"idempotencyKey": "1b4e28ba-2fa1-41d2-883f-0016d3cca427"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
action: 'buy',
type: 'limit',
instrumentId: 'ins_0123456789AB',
side: 'yes',
count: 10,
limitPriceCents: 40,
timeInForce: 'gtc',
idempotencyKey: '1b4e28ba-2fa1-41d2-883f-0016d3cca427'
})
};
fetch('https://arena-predictions.com/api/v1/portfolio/orders', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"status": "executed",
"action": "buy",
"type": "market",
"idempotencyKey": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"replayed": true,
"originalCreatedAt": "2023-11-07T05:31:56Z",
"order": {
"orderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action": "buy",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"orderSide": "yes",
"contracts": 123,
"filledContracts": 123,
"remainingContracts": 123,
"limitCents": 123,
"holdDollars": 123,
"timeInForce": "<string>",
"expiresAt": "2023-11-07T05:31:56Z",
"status": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"type": "limit",
"cancelReason": "<string>",
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"marketTicker": "<string>",
"fillPriceCents": 123
},
"trade": {
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"boughtSide": "yes",
"contracts": 123,
"costDollars": 123,
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"parlayId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"fillVenue": "<string>",
"openedAt": "2023-11-07T05:31:56Z",
"status": "open",
"closedAt": "2023-11-07T05:31:56Z",
"closeReason": "<string>",
"pnlDollars": 123,
"resolvedOutcome": "yes",
"marketTicker": "<string>",
"entryCents": 123
},
"fillVenue": "kalshi",
"mode": "paper",
"venueData": true,
"fillPriceCents": 123
}{
"status": "executed",
"action": "buy",
"type": "market",
"idempotencyKey": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"replayed": true,
"originalCreatedAt": "2023-11-07T05:31:56Z",
"order": {
"orderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action": "buy",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"orderSide": "yes",
"contracts": 123,
"filledContracts": 123,
"remainingContracts": 123,
"limitCents": 123,
"holdDollars": 123,
"timeInForce": "<string>",
"expiresAt": "2023-11-07T05:31:56Z",
"status": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"type": "limit",
"cancelReason": "<string>",
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"marketTicker": "<string>",
"fillPriceCents": 123
},
"trade": {
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"boughtSide": "yes",
"contracts": 123,
"costDollars": 123,
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"parlayId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"fillVenue": "<string>",
"openedAt": "2023-11-07T05:31:56Z",
"status": "open",
"closedAt": "2023-11-07T05:31:56Z",
"closeReason": "<string>",
"pnlDollars": 123,
"resolvedOutcome": "yes",
"marketTicker": "<string>",
"entryCents": 123
},
"fillVenue": "kalshi",
"mode": "paper",
"venueData": true,
"fillPriceCents": 123
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}Place a paper order
Places a paper order for the key owner, as the CLI and the MCP server do. Kalshi’s path; paper only, so nothing is sent to Kalshi or any venue. A market order fills now at the live price or is refused. A limit order fills at limitPriceCents or better, rests until it fills, is canceled or expires (gtc), or is canceled at once when it does not fill (ioc, fok). Opening a position needs Arena Basic. Every order counts against the hard trade limits (per key 10 new orders a minute and 50 a day, 20 sells and cancels a minute; per account 20, 100 and 40), which are always enforced. No ticker, title or price in the answer while the venue-data switch is off.
curl --request POST \
--url https://arena-predictions.com/api/v1/portfolio/orders \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"action": "buy",
"type": "limit",
"instrumentId": "ins_0123456789AB",
"side": "yes",
"count": 10,
"limitPriceCents": 40,
"timeInForce": "gtc",
"idempotencyKey": "1b4e28ba-2fa1-41d2-883f-0016d3cca427"
}
'import requests
url = "https://arena-predictions.com/api/v1/portfolio/orders"
payload = {
"action": "buy",
"type": "limit",
"instrumentId": "ins_0123456789AB",
"side": "yes",
"count": 10,
"limitPriceCents": 40,
"timeInForce": "gtc",
"idempotencyKey": "1b4e28ba-2fa1-41d2-883f-0016d3cca427"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
action: 'buy',
type: 'limit',
instrumentId: 'ins_0123456789AB',
side: 'yes',
count: 10,
limitPriceCents: 40,
timeInForce: 'gtc',
idempotencyKey: '1b4e28ba-2fa1-41d2-883f-0016d3cca427'
})
};
fetch('https://arena-predictions.com/api/v1/portfolio/orders', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"status": "executed",
"action": "buy",
"type": "market",
"idempotencyKey": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"replayed": true,
"originalCreatedAt": "2023-11-07T05:31:56Z",
"order": {
"orderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action": "buy",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"orderSide": "yes",
"contracts": 123,
"filledContracts": 123,
"remainingContracts": 123,
"limitCents": 123,
"holdDollars": 123,
"timeInForce": "<string>",
"expiresAt": "2023-11-07T05:31:56Z",
"status": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"type": "limit",
"cancelReason": "<string>",
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"marketTicker": "<string>",
"fillPriceCents": 123
},
"trade": {
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"boughtSide": "yes",
"contracts": 123,
"costDollars": 123,
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"parlayId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"fillVenue": "<string>",
"openedAt": "2023-11-07T05:31:56Z",
"status": "open",
"closedAt": "2023-11-07T05:31:56Z",
"closeReason": "<string>",
"pnlDollars": 123,
"resolvedOutcome": "yes",
"marketTicker": "<string>",
"entryCents": 123
},
"fillVenue": "kalshi",
"mode": "paper",
"venueData": true,
"fillPriceCents": 123
}{
"status": "executed",
"action": "buy",
"type": "market",
"idempotencyKey": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"replayed": true,
"originalCreatedAt": "2023-11-07T05:31:56Z",
"order": {
"orderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action": "buy",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"orderSide": "yes",
"contracts": 123,
"filledContracts": 123,
"remainingContracts": 123,
"limitCents": 123,
"holdDollars": 123,
"timeInForce": "<string>",
"expiresAt": "2023-11-07T05:31:56Z",
"status": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"type": "limit",
"cancelReason": "<string>",
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"marketTicker": "<string>",
"fillPriceCents": 123
},
"trade": {
"tradeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"instrumentId": "<string>",
"instrumentLabel": "<string>",
"instrumentSide": "yes",
"boughtSide": "yes",
"contracts": 123,
"costDollars": 123,
"statedProbPct": 123,
"placedVia": "<string>",
"placedPrivate": true,
"parlayId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"fillVenue": "<string>",
"openedAt": "2023-11-07T05:31:56Z",
"status": "open",
"closedAt": "2023-11-07T05:31:56Z",
"closeReason": "<string>",
"pnlDollars": 123,
"resolvedOutcome": "yes",
"marketTicker": "<string>",
"entryCents": 123
},
"fillVenue": "kalshi",
"mode": "paper",
"venueData": true,
"fillPriceCents": 123
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"retryAfterSeconds": 2
}
}Authorizations
Authorization: Bearer arena_sk_... (the x-arena-key header is accepted too). Keys are made in Settings (https://arena-predictions.com/settings#api-keys) or with arena keys create, shown once, stored hashed.
Body
A buy names instrumentId or ticker, side and count. A sell names tradeId and covers the whole open position. A limit order adds limitPriceCents. Unknown fields are refused (400), so a typo never changes an order.
market: fills now at the live price or is refused. limit: fills at limitPriceCents or better, or rests (gtc), or is canceled (ioc, fok).
market, limit One per order. The same key again answers the stored order with replayed: true and places nothing; the same key with a different order is 409 idempotency_key_reused. Retry with the same key after a timeout or a 503.
buy, sell Kalshi's name for idempotencyKey. Send one of the two.
Buy: the Arena instrument; side is the instrument's side. It must list on one live Kalshi market (409 no_tradable_listing otherwise).
^ins_[0-9A-HJKMNP-TV-Z]{12}$Buy: a Kalshi market ticker instead of instrumentId; side is the market's side. Never echoed back while the venue-data switch is off.
Buy: the side to buy.
yes, no Buy: contracts. Your paper balance is the limit.
1 <= x <= 1000000000Sell: the open position (GET /portfolio).
Limit: your price for the side you trade, in cents (a percent).
1 <= x <= 99gtc, ioc, fok, good_till_canceled, immediate_or_cancel, fill_or_kill gtc only: when the order stops resting. At most 365 days out.
Market buy: refuse to fill above this (409 price_moved, nothing placed).
1 <= x <= 99Market sell: refuse to sell below this (409 price_moved, nothing sold).
1 <= x <= 99best: a fill may be priced at Novig's or Polymarket's price when it passes every check. Omitted: Kalshi's.
kalshi, best Buy: your probability for the side. Never changes the fill; scored on /eval.
1 <= x <= 99Response
A replay: this idempotencyKey was used before for the same order. Nothing new was placed.
canceled: an ioc or fok that did not fill. Nothing was spent.
executed, resting, canceled buy, sell market, limit True when this idempotencyKey was used before: the stored order, nothing new placed.
On a replay: when the order was first placed.
The limit order. Null for a market order, which is a fill and not an order.
Show child attributes
Show child attributes
The position opened (buy) or closed (sell). Null while resting or canceled.
Show child attributes
Show child attributes
Where the fill was priced. Paper only: nothing is sent there.
kalshi, novig, polymarket, null "paper"Only while the venue-data switch is on.