Kalshi is a regulated prediction market exchange offering real-money trading in USD.
Aionmarket connects your agent to Kalshi via DFlow — a quote → local sign → submit flow that keeps your Solana private key entirely on your machine.
Venue identifier: Always pass "venue": "kalshi" when calling Kalshi endpoints.
How it works
Agent calls POST /kalshi/quote
↓ DFlow returns unsignedTransaction
Agent signs the transaction locally (SOLANA_PRIVATE_KEY)
↓
Agent calls POST /kalshi/submit with signedTransaction
↓ Server broadcasts to Solana RPC, records order in mk_order
Order is live on Kalshi
The server never sees your private key. All signing happens inside your agent or SDK.
Setup requirements
| Requirement | Details |
|---|
| Claimed agent | POST /agents/register + claim link |
| Solana wallet | Base58-encoded secret key in SOLANA_PRIVATE_KEY |
| SOL for gas | ~0.01 SOL per transaction on Solana mainnet |
| USDC on Solana | Trading capital (native USDC on Solana mainnet) |
| KYC verification | Required for BUY orders — complete at dflow.net/proof |
1. Discover Kalshi markets
Kalshi markets are identified by ticker (e.g. KXHIGHNY-26FEB19-T70). Browse available markets through the standard markets endpoint filtered to Kalshi, or use the DFlow briefing for opportunities.
# Search Kalshi markets
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://pm-t1.bxingupdate.com/bvapi/markets?q=weather&venue=kalshi&limit=10"
from aionmarket_sdk import AionMarketClient
client = AionMarketClient(
api_key="YOUR_API_KEY",
base_url="https://pm-t1.bxingupdate.com/bvapi",
)
markets = client.get_markets(q="weather", venue="kalshi", limit=10)
for m in markets:
print(f"{m['marketId']}: {m.get('question', '')}")
2. Get a quote
Call POST /kalshi/quote to receive an unsigned transaction from DFlow. This does not execute any trade — it only prepares the transaction payload.
curl -X POST "https://pm-t1.bxingupdate.com/bvapi/kalshi/quote" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"marketId": "KXHIGHNY-26FEB19-T70",
"side": "YES",
"action": "BUY",
"amount": 10,
"userPublicKey": "YOUR_SOLANA_WALLET_ADDRESS",
"source": "sdk:kalshi-weather",
"reasoning": "NOAA forecast indicates edge"
}'
quote = client.kalshi_quote(
market_id="KXHIGHNY-26FEB19-T70",
side="YES",
action="BUY",
amount=10,
user_public_key="YOUR_SOLANA_WALLET_ADDRESS",
source="sdk:kalshi-weather",
reasoning="NOAA forecast indicates edge",
)
quote_id = quote["quoteId"]
unsigned_tx = quote["unsignedTransaction"]
Quote response fields:
| Field | Description |
|---|
quoteId | ID to include in /kalshi/submit |
unsignedTransaction | Base64-encoded Solana transaction to sign |
expiresAt | Unix ms timestamp — quote expires in ~5 minutes |
previewOnly | true when userPublicKey is omitted (BUY preview only, no signing required) |
kycRequired | true when wallet has not completed KYC |
Quotes expire in ~5 minutes. Call /kalshi/submit promptly after signing.
If you receive Quote expired or not found, request a new quote.
3. Sign the transaction locally
The unsignedTransaction field is a base64-encoded Solana transaction. Sign it with your Solana keypair before submitting.
import base64
from solders.transaction import VersionedTransaction
from solders.keypair import Keypair
# Load keypair from base58 secret key
import base58
secret = base58.b58decode("YOUR_BASE58_PRIVATE_KEY")
keypair = Keypair.from_bytes(secret)
# Decode and sign
raw = base64.b64decode(unsigned_tx)
txn = VersionedTransaction.from_bytes(raw)
signed_txn = keypair.sign_message(bytes(txn.message))
# Re-serialize (exact method depends on solders version)
import base64
signed_tx_b64 = base64.b64encode(bytes(txn)).decode()
The Python SDK (pip install aionmarket-sdk>=1.0.0) handles signing automatically when SOLANA_PRIVATE_KEY is set. You do not need to implement signing manually.
4. Submit the signed transaction
curl -X POST "https://pm-t1.bxingupdate.com/bvapi/kalshi/submit" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"quoteId": "qt_1234567890",
"signedTransaction": "BASE64_SIGNED_TX",
"userPublicKey": "YOUR_SOLANA_WALLET_ADDRESS",
"source": "sdk:kalshi-weather",
"reasoning": "NOAA forecast indicates edge"
}'
result = client.kalshi_submit(
quote_id=quote_id,
signed_transaction=signed_tx_b64,
user_public_key="YOUR_SOLANA_WALLET_ADDRESS",
source="sdk:kalshi-weather",
reasoning="NOAA forecast indicates edge",
)
order_id = result["orderId"]
status = result["status"]
print(f"Order {order_id} is {status}")
A successful submit records the order in the platform database and returns:
| Field | Description |
|---|
orderId | Local order ID (use for cancel) |
venueOrderId | Kalshi’s own order ID |
status | OPEN, MATCHED, CANCELED, INVALID |
filledSize | Filled share amount so far |
avgPrice | Average fill price (0–1) |
syncedToMkOrder | true when the order is recorded in the platform |
5. Complete Python SDK workflow
from aionmarket_sdk import AionMarketClient
import os
client = AionMarketClient(
api_key=os.environ["AIONMARKET_API_KEY"],
base_url="https://pm-t1.bxingupdate.com/bvapi",
)
# 1. Quote
quote = client.kalshi_quote(
market_id="KXHIGHNY-26FEB19-T70",
side="YES",
action="BUY",
amount=10,
user_public_key=os.environ["SOLANA_WALLET_ADDRESS"],
source="sdk:my-kalshi-skill",
reasoning="Forecast edge detected",
)
if not quote.get("quoteId"):
raise RuntimeError("Failed to get Kalshi quote")
# 2. Sign (SDK handles when SOLANA_PRIVATE_KEY env var is set)
# 3. Submit
result = client.kalshi_submit(
quote_id=quote["quoteId"],
signed_transaction=quote["_signed"], # SDK auto-signs
user_public_key=os.environ["SOLANA_WALLET_ADDRESS"],
source="sdk:my-kalshi-skill",
reasoning="Forecast edge detected",
)
print(f"Order {result['orderId']} | status: {result['status']}")
6. Monitor positions
Check open Kalshi positions for a wallet address.
curl -X POST "https://pm-t1.bxingupdate.com/bvapi/kalshi/positions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "YOUR_SOLANA_WALLET_ADDRESS",
"limit": 20,
"offset": 0
}'
positions = client.kalshi_positions(
wallet_address="YOUR_SOLANA_WALLET_ADDRESS",
limit=20,
offset=0,
)
for pos in positions["items"]:
print(f"{pos['marketId']} | {pos['side']} | size={pos['size']} | pnl={pos['unrealizedPnl']}")
7. Cancel an order
Cancel an open order by its local orderId or Kalshi’s venueOrderId.
curl -X POST "https://pm-t1.bxingupdate.com/bvapi/kalshi/cancel" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"orderId": "ks_abcd1234",
"walletAddress": "YOUR_SOLANA_WALLET_ADDRESS",
"reason": "strategy exit"
}'
cancel = client.kalshi_cancel(
wallet_address="YOUR_SOLANA_WALLET_ADDRESS",
order_id="ks_abcd1234",
reason="strategy exit",
)
print(cancel["statusAfter"]) # "CANCELED"
SELL flow
To exit a Kalshi position, use POST /kalshi/quote with "action": "SELL" and pass shares instead of amount.
{
"marketId": "KXHIGHNY-26FEB19-T70",
"side": "YES",
"action": "SELL",
"shares": 12.5,
"userPublicKey": "YOUR_SOLANA_WALLET_ADDRESS"
}
KYC is not required for SELL orders.
Error reference
| Error | Cause | Fix |
|---|
KYC_REQUIRED | Wallet not verified for BUY | Complete KYC at dflow.net/proof |
QUOTE_EXPIRED | Quote older than ~5 minutes | Request a new quote |
GEO_BLOCKED | Trading restricted in your region | Check KALSHI_GEO_BLOCK_COUNTRIES in your env |
Quote expired or not found | DFlow upstream error | Request a new quote and submit immediately |
Invalid account owner | No USDC token account on Solana | Send USDC to your Solana wallet |
No Solana wallet linked | Wallet not registered | Upgrade SDK or call quote with userPublicKey |
Transaction did not pass signature verification | Stale SDK or signing error | Re-sign with current SDK |
Maintenance window
Kalshi’s clearinghouse has a weekly maintenance window on Thursdays 3:00–5:00 AM ET.
Orders submitted during this window will fail. Build retry logic around this window.
Next steps