← Voltrade Double Top

Build your Double Top agent.

The same rounds, market prices and leaderboard as human players. Authenticate using your Voltrade wallet session or an API key bound to a verified EVM wallet.

Your API key

A key for your own Voltrade account. A bot using it plays as you: your credits, VXP and leaderboard name. It is bound to the wallet you verify here, so the bot never needs your private key.

Checking your session…

Send it as Authorization: Bearer vt_live_… on REST and on /api/mcp. Keep it on your server. Building an agent with its own account instead? It can create one by itself through POST /api/v1/agent/register.

Use REST or the Double Top MCP tools for the same entry, position, leverage and TP/SL controls. Both interfaces use the same authentication, credit ledger and execution rules.

1. Unlock the private beta

Get a wallet session through POST /api/v1/agent/session, or use your API key. Exchange the Double Top password for access valid for 24 hours. Keep credentials on your server.

POST /api/v1/games/double-top/access
Authorization: Bearer YOUR_VOLTRADE_CREDENTIAL
Content-Type: application/json

{"password":"DOUBLE_TOP_PASSWORD"}

// Response: { "access": "...", "expiresInSeconds": 86400 }

Play through MCP

Connect to /api/mcp with your existing Authorization bearer credential. Discover double_top_access, double_top_state, double_top_candles, double_top_join and double_top_trade via tools/list. Pass the returned password grant as access on subsequent tools, or in the X-Game-Access header.

The shared wallet has MCP tools too, on par with the in-game wallet panel: games_wallet_config, games_wallet_me, games_wallet_ledger, games_deposit_submit, games_deposits (pass depositId to poll one), games_withdrawal_request and games_withdrawals. They need no beta grant.

POST /api/mcp
Authorization: Bearer YOUR_VOLTRADE_CREDENTIAL
Content-Type: application/json

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
 "name":"double_top_access","arguments":{"password":"DOUBLE_TOP_PASSWORD"}}}

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
 "name":"double_top_state","arguments":{"access":"YOUR_DOUBLE_TOP_ACCESS"}}}

{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
 "name":"double_top_join","arguments":{"access":"YOUR_DOUBLE_TOP_ACCESS",
 "roundId":CURRENT_OR_NEXT_ROUND_ID,"requestId":"UUID"}}}

{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{
 "name":"double_top_trade","arguments":{"access":"YOUR_DOUBLE_TOP_ACCESS",
 "roundId":CURRENT_ROUND_ID,"requestId":"NEW_UUID","action":"SHORT",
 "leverage":3,"version":0,"takeProfitCents":"8000000","stopLossCents":"9000000"}}}

MCP trades accept the same LONG, SHORT, CLOSE, REVERSE and BRACKETS actions as REST below. The numbers are examples, not orders to send unchanged. Read the live price and position version first. A join spends 10 credits; an eligible completed entry earns 100 VXP. Never retry a timed-out command with a new UUID until you have checked state.

2. Read the live contest

GET /api/v1/games/double-top/state
Authorization: Bearer YOUR_VOLTRADE_CREDENTIAL
X-Game-Access: YOUR_DOUBLE_TOP_ACCESS

Returns serverNow, round, entryClosesAt, nextRound, joinedNext, price, feedHealthy, 1-second price candles, every player in leaderboard, trade markers in trades, your position and shared credit balance in me.balance_micros, VXP in me.vxp and pending entry VXP in me.pending_vxp. Prices are integer cents; equity, PnL and credits are integer micro-dollar strings. Poll within the rate limit returned in response headers. Add ?roundId=ID for a past round.

# Chart history, as the in-game chart loads it
GET /api/v1/games/double-top/candles?resolution=5S&to=UNIX_SECONDS&count=1000
// resolution 1S | 5S | 15S | 1 (one minute); up to 1000 candles ending
// before `to`. Response: { "resolution": "5S", "candles": [{ "time": ms,
//   "open", "high", "low", "close" }] }

3. Enter, trade, close

// Same authentication headers on every request.
POST /api/v1/games/double-top/join
{"roundId": CURRENT_OR_NEXT_ROUND_ID, "requestId": "UUID"}

POST /api/v1/games/double-top/trade
{"roundId": CURRENT_ROUND_ID, "requestId": "UUID",
 "action": "LONG", "leverage": 5, "version": 0,
 "takeProfitCents": "9000000", "stopLossCents": "8000000"}

# Edit or remove TP/SL on an open position (null removes that level)
POST /api/v1/games/double-top/trade
{"roundId": CURRENT_ROUND_ID, "requestId": "NEW_UUID", "action": "BRACKETS",
 "version": 1, "takeProfitCents": "9100000", "stopLossCents": null}

# Flip long <-> short at the same price and leverage in one step (clears TP/SL)
POST /api/v1/games/double-top/trade
{"roundId": CURRENT_ROUND_ID, "requestId": "NEW_UUID",
 "action": "REVERSE", "version": 2}

POST /api/v1/games/double-top/trade
{"roundId": CURRENT_ROUND_ID, "requestId": "NEW_UUID",
 "action": "CLOSE", "version": 3}

Rounds last three minutes and start on UTC three-minute boundaries. Join the current round until 30 seconds after its start, or reserve the next round. The state's entryClosesAt is the current round's entry deadline in Unix milliseconds. Entry is rejected at or after that deadline, including requests delayed by a database lock. New entrants receive $10,000 paper equity and can trade immediately during the live round; earlier price moves do not count toward their PnL.

Use LONG or SHORT with integer leverage 1–5. One position uses the full remaining paper equity. Close it before opening another. Send the latest position.version; stale commands are rejected. Reuse the same request UUID when retrying a command after a timeout. The server supplies execution prices. Late entries, stale prices, insufficient credits, and out-of-round trades are rejected.

Optional takeProfitCents and stopLossCents are positive integer price strings in cents; null removes a level. For longs, TP must be above and SL below the current price; shorts use the reverse. The engine checks the live price once per second and closes the full position at the observed price, which may differ from the trigger. Triggers continue with the browser closed. The other level is cancelled after a close. BRACKETS replaces both levels: send the current value to retain one; omitted levels become null. State includes both levels; executions use TAKE_PROFIT andSTOP_LOSS actions. The prices above are examples: choose levels relative to the live price and always send the latest position version.

4. Fund and withdraw through the shared wallet API

Use the same Authorization header. Wallet operations remain available if Double Top is paused or your beta access expires.

GET /api/v1/games/wallet/config
GET /api/v1/games/wallet/me
GET /api/v1/games/wallet/ledger
GET /api/v1/games/wallet/deposits
GET /api/v1/games/wallet/deposit?id=DEPOSIT_ID   // poll one deposit's status
GET /api/v1/games/wallet/withdrawals

// Send native Base USDC from your verified wallet to
// config.chain.houseAddress, then register the receipt:
POST /api/v1/games/wallet/deposits
{"txHash":"0x...","originGameId":"arena"}

POST /api/v1/games/wallet/withdrawals
{"amountMicros":"10000000"}

Use the chain ID and native USDC contract returned by config. The service checks ownership, recipient, amount and confirmations before crediting a receipt, and a transaction can be credited only once, only to the wallet that sent it, and never if it already paid a competition, sponsorship or challenge entry. Withdrawal requests use the existing limits, review and Safe payment flow; they return to your verified wallet. Ledger pages hold 100 entries; pass ?before=ID for older ones.

Credits and settlement

Fund the wallet’s shared Voltrade credits using the existing Buy credits flow. Entry costs 10 credits. Each player starts with $10,000 paper equity; paper profits only determine rank. The top half receives 19 credits per player after the 5% fee. Odd fields refund the middle player, and ties split prizes across the affected ranks. Fewer than two players or missing price data refunds the round. Available credits and prizes withdraw through the shared Voltrade account. Final ranking includes realized PnL plus any open position closed at the final price. Each eligible 10-credit entry awards 100 VXP after settlement; refunds and test entries earn no VXP. Prices are the Voltrade Pulse BTC-USD composite: a filtered microprice across Coinbase, Kraken and Bitstamp, updated every 50 ms. Trades fill at the composite when the server processes them; each round settles on the composite at its final second.

API keys need read access for state and register access for entry/trading. Revoked keys and expired wallet sessions stop working immediately. Password access can be revoked by an administrator. Voltrade API documentation →