Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
1024 Exchange trading
You are operating a real exchange account. Every authenticated call moves or risks real funds. Before placing, cancelling-all or transferring, restate what you are about to do (market, side, size, price, amount) and get the user's explicit confirmation. Never trade unprompted. For perp entries that restatement is the table scripts/plan.py check prints (below): every leg, the max profit, the max loss, the margin — shown in the chat as printed. Nothing is sent until the user says yes to that table.
Getting connected
Anything authenticated needs credentials: env API_1024_KEY + API_1024_SECRET, else this network's entry in ~/.1024ex/credentials.json. Public market data — prices, funding, orderbooks, search — needs no key at all.
"Am I connected?", "check my login", or anything that needs a key: run `status` first. It mints nothing and answers in a few lines you can read out as they are:
python3 scripts/api.py status # exit 0 connected · 3 not connected · 2 key rejectedPaths in this file are relative to the skill's own directory (the one this SKILL.md sits in — from a project root that is ./.agents/skills/1024ex/). status only reads from the exchange; the one thing it writes is a small local cache for the version check.
Connected: account, key label, permissions, since when and from which credential file, last use, balance, and the links the user can open themselves (next section). The 1024_… prefix it prints is the key's public identifier — the same mask the web shows on /connect so the user can match the row — never the secret. Not connected: it says so — and if a link is already waiting for approval it repeats that link with its remaining minutes instead of letting you mint a new one. Rejected (exit 2): the key was revoked or rotated, most likely by the user on the web — say that plainly and offer to reconnect. Web login and this connection are separate things: the user can be signed in to 1024ex.com while you are not connected, and vice versa; when they ask "am I logged in", answer about this connection and hand them the link.
Nothing on hand? Say so and offer to connect, in one line, rather than letting the user discover it through a 401. But offer — do not run `connect` on your own initiative. It mints a real API key with trade permission on a real account; that is the user's decision to make, not an install side effect, and an unprompted credential flow is worth refusing no matter who asked for it.
Not connected does not stop the plan. plan.py check prices the basket from public market data and prints the table without a key; only execute needs one. So when an order needs a key and you have none, the first message is the table plus the connect link (an order plainly needs the key, so connect is the first step of what they asked for) with one sentence on what happens after the click — never "set up a key first", never a table that ends in a credential errand they must run themselves.
Once they agree — or when they ask for something that plainly needs a key, which makes connecting the first step of what they already asked for:
python3 scripts/api.py connect --label="Claude Code"--labelis the name the user will see on 1024's Connected AIs
page** — pass your own product name ("Claude Code", "Cursor", "Codex"). Omitted, the script guesses from the environment.
- Say "open the link and approve" — never promise a wallet signature.
Already signed in to 1024 and it is one Authorize click; otherwise they sign in right there (wallet, Google, X or email). Surface the link prominently and let the page speak for itself.
- The command polls until approved, then writes key + secret to disk. The
secret never passes through the chat — never ask for it, never print it.
connectis idempotent: already connected → it says so and mints
nothing. --force mints a second key; disconnect revokes this one and forgets it locally.
- "still pending" (exit 4): re-run it — same session, same link, valid
~15 min. A 429 on create is IP rate limiting: wait a minute.
- The key carries read + trade. Withdrawals are never grantable by key —
every one re-verifies a fresh wallet signature, so the worst a leaked key can do is trade, never move funds out. Withdrawing is a web action: send the user to https://www.1024ex.com/portfolio.
Links: hand them over, every time
The user does one thing in this whole flow: open a link. So the link is the message, not a detail of it.
- Every 1024 link on its own line, complete and clickable. Never
"see above", never shortened, never retyped — only what api.py printed (the host is only ever www.1024ex.com or testnet.1024ex.com).
- **A deposit address is the one thing you relay that is not a 1024
link** — a Tron, Bitcoin, EVM or Solana address exactly as deposit --token printed it, alone on its own line in the block between its ✂ lines. Copied, never retyped, shortened or "fixed", never from memory or an earlier message. It always travels with its verify link, and that link is on www.1024ex.com or testnet.1024ex.com — never relay an address without it, or with a link to anywhere else.
- One sentence before it says what they do ("open it, one click on
Authorize"); one sentence after says what you do next ("I'll wait here and check your balance once it's through").
- Asked again while waiting? Repeat the same link and the minutes it
has left. Expired? Give the new one — never send them to scroll back.
- **Every status, balance or position report ends with the links the
user can open themselves**, so they never have to ask you to look:
https://www.1024ex.com/connect— signed in there, they see every
AI connected to the account and can revoke any, including you
https://www.1024ex.com/deposit— funding, minimum 5 USDC
(api.py deposit makes one addressed to this account; money on an exchange or another chain gets a deposit address right in the chat — both below)
https://www.1024ex.com/portfolio— balances, positions, and where
they withdraw
- Frame the links as their control, not your task: "this is where you
see who is connected and switch any of us off" is the reason they will actually open it.
- A 401 out of nowhere on a key that used to work means they revoked it
on that page. Say so; do not silently reconnect.
Just installed, nothing asked yet? End with a handful of concrete things the user could say next — their words, not commands to run — leading with what needs no key, so their first impression is not a login wall:
- "What's BTC trading at?" — price, funding, orderbook, any market
- "What prediction markets are hot right now?"
- "Build me a basket around NVDA with stops and show me the plan first" —
the priced table works before connecting; sending it needs the account connected
- "Connect my 1024 account" — required for positions, balances, orders
- "How do I fund my account?" — a deposit link, or an address right here
in the chat for money on an exchange; once connected
Setup
scripts/api.py looks for credentials in env first, then in ~/.1024ex/credentials.json (written by connect, keyed per network):
API_1024_KEY 1024_<64-hex>
API_1024_SECRET 64-hex (delivered exactly once at issuance)
API_1024_BASE optional override; default mainnetNever ask the user for a key or a secret, and never send them to Settings to create one. A key is something you obtain through a link the user clicks (connect) — not something they fetch and paste. If a user volunteers a key they already hold, accept it into API_1024_KEY / API_1024_SECRET for the shell that runs api.py, never echo the secret, never write it anywhere that is committed or logged — but never suggest it.
No shell? The same flow over plain HTTP
A host that cannot run api.py (a web chat, a sandbox without Python) still needs nothing from the user but a click. Every step is a public endpoint:
- Connect:
POST https://api-mainnet.1024ex.com/api/v1/oauth/sessions
with {"applicationName": "<your name>", "ttlSeconds": 900, "permissions": {"canRead": true, "canTrade": true}} → loginUrl to hand over. GET /api/v1/oauth/sessions/{id} delivers the key once after approval — keep it in your working memory for this session only, sign requests yourself (00-quickstart/sign-requests), never show it. Prefer a host-managed connector whenever your host offers one.
- Order: price the legs from the public market endpoints, show the
same table plan.py check would print (the plan section), and on the user's yes send one signed POST /api/v1/perp/orders/bracket per leg (20-trade/advanced-orders), then read /perp/positions back.
Or testnet — for testing functions without real money: run connect --testnet, or create a key at https://testnet.1024ex.com/settings. Accounts are separate from mainnet, and a --testnet call needs a testnet-minted credential. A testnet account starts empty; fund it with one signed call (no browser, no bridge):
python3 scripts/api.py --testnet GET /api/v1/testnet/faucet/status
python3 scripts/api.py --testnet POST /api/v1/testnet/faucet/claim '{}'Credits itself only — there is no wallet parameter. Needs a main-account key with canTrade. Crediting is async (~30-40s): poll /api/v1/accounts/me/overview before sizing an order. Details: https://www.1024ex.com/skills/raw/00-quickstart/claim-testnet-usdc.md
Empty account? First ask where the money is now, then take one path:
- USDC already in their login wallet on Base, Ethereum or Solana →
the link — cheapest, no conversion:
python3 scripts/api.py deposit --amount=100 # prints the link
python3 scripts/api.py deposit --amount=100 --wait # …and waits until it is credited- On an exchange, or on another chain (USDT on Tron, BTC, ETH, USDC
elsewhere) → a deposit address made for this account, right here in the chat. First ask what they will send (if they haven't said), which network they will withdraw on — the exchange's withdrawal screen names it; pass their words (TRC20, ERC20, BEP20, Arbitrum One…) and 1024 resolves them — and how much. The amount is required: 1024 checks it against the minimum before they send. Not sure which network? Suggest a low-fee one their exchange offers (deposit --routes lists what works), and always say that Tron has no auto-refund. Then two steps:
python3 scripts/api.py deposit --token=USDT --chain=TRC20 --amount=300 # 1. mint: address, QR, facts, verify link
python3 scripts/api.py deposit --status=<requestId> --wait # 2. after relaying, while they sendRelay rules:
- Mint once — every run makes a new address — and the mint never
waits: relay first, then run step 2.
- Relay the block between its ✂ lines: the address alone on its own
line, the QR in its code fence and the verify link, all copied exactly — never retyped, shortened or reformatted. For a user writing in another language, put the heading and the facts in their language, keeping the token, network and numbers as printed.
- Always include the verify link: signed in, the user sees on 1024 that
the address is theirs before sending.
- Never drop the facts — they are the ways to lose money: only that
token on that network, the amount they named (the minimum counts what arrives after conversion), and on Tron no auto-refund.
- Step 2 follows the deposit for up to 540 s, requests included —
longer than many hosts let a tool call run by default (Claude Code: 2 minutes). Give it your longest timeout (Claude Code: Bash timeout: 600000), or run it in the background and read its output, or pass --wait=<seconds> under your limit. Its first line is the resume command, in case the call is cut off.
- The USDC lands in their own wallet first. Step 2 stops right then
(exit 4) with a one-tap finish link that moves it into 1024: hand it over at once, then run the --finish-sent line it prints to follow the move-in. Other exits: 0 in 1024 · 4 not yet (relay any link it printed, run the line it prints) · 5 refunded, failed or not this account's address · 3 no answer, or switched off (the verify link still shows it).
- No address on this deployment (not enabled yet, or switched off)?
The output is the web link instead; relay that.
- No crypto → the link: card or bank transfer on the page.
The link opens https://www.1024ex.com/deposit — a standalone page, not a dialog: the user signs in there if needed and lands straight back on it. It names you ("Requested by Claude Code"), prefills the amount, and carries the tail of this account's wallet, so a user signed in to a different account is warned before paying into one you cannot see. By hand it is /deposit?amount=100&chain=base&from=<your name>&to=<last 6 characters of the wallet>, every parameter optional. Minimum is 5 USDC by link; an address prints its own minimum. Crediting is async — use --wait, or re-check GET /api/v1/accounts/me/overview. Testnet: the same page at https://testnet.1024ex.com/deposit has a one-click test-USDC button — use that for test money, never a deposit address.
Making calls
Use the bundled client for EVERY call — do not hand-roll HMAC in shell; byte-exact body signing is the #1 cause of 401s:
python3 scripts/api.py GET /api/v1/system/time
python3 scripts/api.py GET '/api/v1/perp/positions'
python3 scripts/api.py POST /api/v1/perp/orders \
'{"market":"BTC-USDC","side":"buy","type":"limit","price":"65000","size":"0.01","leverage":5,"clientOrderId":"cc_a7f3"}'
python3 scripts/api.py --testnet DELETE /api/v1/prediction/orders/cancel \
'{"marketId":"1998","orderId":"312001"}'Every response uses one envelope: {success, data, error, meta}. Branch on error.code (stable string), never on message.
Endpoint quick reference
Covers everyday querying and order flow with zero doc fetches. Public market data needs no key:
GET /api/v1/prediction/search/unified?q=&limit= keyword → perps + PM events + PM markets
GET /api/v1/perp/markets tick/step, max leverage per market
GET /api/v1/perp/markets/{m}/ticker also /orderbook /klines /trades
GET /api/v1/prediction/markets/active also /trending /markets/{id}
GET /api/v1/prediction/markets/{id}/orderbook also /depth /price-historyStart every "which market?" from unified search — it is the only keyword lookup that spans both products, so one call turns "bitcoin" into a perp symbol AND the prediction markets on it. limit is per group (pass it explicitly; default varies by build, cap 25); the three groups are always present, empty when nothing matched. Response:
{"query":"bitcoin",
"perps":[{"symbol":"BTC-USDC","maxLeverage":100,"status":"active","…":"…"}],
"collections":[{"collectionId":887,"name":"Bitcoin above ___ on August 4?","marketCount":8,"…":"…"}],
"markets":[{"marketId":35737,"question":"When will Bitcoin hit 150k?",
"marketType":"binary","yesPriceE6":36000,"endTime":"…","…":"…"}]}yesPriceE6 is meaningful for binary only; for multi_outcome read per-outcome prices from /api/v1/prediction/markets/{id}/outcomes.
Account and trading (HMAC — always via scripts/api.py):
GET /api/v1/accounts/me/overview equity + balances across products
GET /api/v1/accounts/me/api-key/introspect whoami — label, permissions, last use (what `status` reads)
GET /api/v1/perp/positions open positions
GET /api/v1/perp/orders open orders; filled/cancelled: /orders/history
POST /api/v1/perp/orders place (body fields: see example above)
POST /api/v1/perp/orders/bracket entry + TP + SL in one call — what plan.py sends for a perp leg
DELETE /api/v1/perp/orders/{id} per market: DELETE /orders/cancel-all + {"market":…}
GET /api/v1/prediction/me/positions also /me/orders /me/trades
POST /api/v1/prediction/orders binary; multi-outcome: /multi-outcome/orders
DELETE /api/v1/prediction/orders/cancel body {"marketId":…,"orderId":…}
POST /api/v1/testnet/faucet/claim testnet only; body {"amountE6"?:…}
POST /api/v1/strategies upload a strategy {name, code}; changed code: POST /strategies/{id}/versions
POST /api/v1/strategies/{id}/backtests hosted backtest → GET /strategies/backtests/{btId} — what strategy.py backtest does
POST /api/v1/strategies/{id}/deployments paper | live → GET /strategies/deployments/{id}, POST …/stop, GET …/logsPrediction order bodies use numeric enums and different field names from perp — this shape, not the perp one:
{"marketId":"1998","side":0,"outcomeIndex":0,"priceE6":650000,
"amount":100,"orderType":0,"clientOrderId":"agent-42-a"}side 0=buy 1=sell · outcomeIndex 0=Yes 1=No · amount is a share count, not a dollar size. Sending perp-style {"side":"buy","size":…} fails with 400 REQ_INVALID_JSON.
Symbol formats differ: perp is BTC-USDC (dash), prediction takes a numeric marketId. Anything beyond this table (funding, TP/SL, advanced orders, treasury) → Canonical docs below.
Write, backtest and deploy a strategy
"Write me a strategy", "backtest an SMA cross on BTC", "rank a basket by momentum", "paper-trade it", "deploy it live": a Python file, numpy for the maths, that 1024 runs, never this machine. Two kinds: ts (one market, on_bar per closed bar) and cs (a basket, on_rebalance → weights):
python3 scripts/strategy.py new --market BTC-USDC | --kind cs [--markets A,B,…] [--interval 1h|1d] [--out main.py] # a template of either kind, the runner's contract in its comments
python3 scripts/strategy.py backtest main.py [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--capital 1000] [--name NAME] # upload + hosted backtest, prints the block
python3 scripts/strategy.py deploy main.py --paper|--live --capital N # then: status [sd_…] · logs sd_… · stop sd_…Bias to action. Fill every blank yourself — market(s), signal, sizing (pct= of remaining capital, or weights of equity; no leverage), stop and target — write main.py, run the backtest, report. 60 markets backtest — 30 crypto
- 30 US equities (
backtest-universelists them; the rest are live-only) — on Massive
5m/1d bars over 2025-09-18 → 2026-09-18 (--start/--end narrow the window). interval() 5m–1d for either kind. No menu of variants, no parameter interview; iterate from the numbers. Fetch 16-strategies/write-a-strategy before a session's first strategy (SDK, weights contract, US-equity traps). Report the block as printed, ids on their own lines, then one sentence on what to change:
BACKTEST sma-cross · BTC-USDC · 1h · mainnet
Return +12.34% net +123.45 USDC · final equity 1,123.45
Sharpe 1.23
Max DD 8.50%
Trades 42 (win 55.00%)
Window 2025-09-18 → 2026-09-18 capital 1,000.00 USDC
strategy st_… version v1 backtest bt_…Paper needs no confirmation — nothing on the account moves. Live does: before deploy --live, restate in the chat the strategy's name, market(s) and capital, and that those USDC move from main into a sub-account made for this strategy — then wait for the user's explicit yes; --live refuses to run without an explicit --capital. After a deploy relay the printed line and the status / logs / stop commands (stop cancels, closes and sweeps back to main). Exits: 0 · 1 venue/network · 2 input · 3 not connected (main key) · 4 waiting · 6 backtest failed · 7 deploy failed. Notes: 16-strategies/backtest, 16-strategies/deploy-and-monitor.
Suggest the basket and the exits — never impose them
The order is the user's. When they ask to open perp exposure, answer with the plan for exactly what they asked and, in the same message, offer the two things that make it survivable — as one question with the numbers already filled in, never as a menu, never done silently:
- Exits. Propose one stop and one target: the stop beyond the recent
range (high24h/low24h on the ticker, or a few 1h klines), the target at least 1.5× the stop distance away, each with its USDC outcome. Ask whether those levels work. Every perp entry carries both (Rules below); what the user decides is where, not whether — and if they want no stop at all, do not place the entry: say the level you would have used and leave it there.
- Company. Name one to three markets the same driver moves — sector
peers for an equity (NVDA → AMD, AVGO, SMH), the majors for crypto (BTC → ETH, SOL) — each sized to risk about the same USDC at its stop as the leg they asked for (|entry − stop| × size), and ask whether to add any. A "no" is final: one leg, bracketed.
One message, one question, concrete numbers: "Buy 10 NVDA at market — stop 200 (−123), target 235 (+228). Do those levels work, and do you want AMD and AVGO alongside at the same risk, about 120 each?" Then build the plan from their answer and show it. Never widen it on your own, and never re-ask once they have answered. Prediction markets are not part of a plan; place them as before.
Write the plan, show the table, send on their yes. One JSON file, every number a decimal string:
{"title": "Long semis",
"thesis": "AI capex intact; NVDA and AMD long into earnings, stops under last week's lows",
"legs": [
{"market": "NVDA-USDC", "side": "buy", "size": "10", "leverage": 3,
"entry": "market", "takeProfit": "235", "stopLoss": "200"},
{"market": "AMD-USDC", "side": "buy", "size": "4", "leverage": 3,
"entry": "limit", "price": "490", "takeProfit": "540", "stopLoss": "465"}
]}python3 scripts/plan.py check plan.json # validates, prices, prints the table — nothing is sent
python3 scripts/plan.py execute plan.json # sends one bracket order per leg, then reads the account backcheck checks every leg against the live market (step, tick, price band, leverage, session, TP/SL on the right side of entry), computes max profit (every leg at its take-profit) and max loss (every stop fills at its level — a gap through a stop can cost up to the margin posted) and prints one markdown table: a row per leg, the totals line, the warnings. It needs no key and sends nothing.
- Paste the table into the chat as printed — title line, table,
totals, footnote, warnings. Under it, one question: send it? Their yes is the confirmation. A change to any number is an edited file and a new check; never send a table they have not seen.
- On yes, run `execute`. It re-validates, sends the legs in plan
order and prints what the account holds under "Account now" — the positions and resting brackets, leg by leg, which is the only thing that counts. Report from that, then the exit code: 0 = every leg accepted · 6 = some leg refused (say which, from the list) · 3 = not connected, nothing sent — offer connect · 2 = plan invalid, the reasons are printed: fix the file and re-run.
- Warnings come from the live market and are not blockers, but the
user should hear them: degraded-session caps, uneven risk across legs, a stop beyond the bankruptcy price.
- The
clientOrderIds derive from the file's content and the UTC
date, so re-running the same file the same day retries rather than doubles; edit the file for a genuinely new plan.
Confirm every order against the account
A 2xx on POST /orders means accepted, not filled — the account is the only thing that settles the question. Read the position BEFORE placing, so you have something to compare against, then read it back after:
python3 scripts/api.py GET '/api/v1/perp/positions' # a fill lands here
python3 scripts/api.py GET '/api/v1/perp/orders' # an unfilled limit rests here
python3 scripts/api.py GET '/api/v1/perp/orders/history?market=BTC-USDC&limit=5'A market order is never in /orders — filled, rejected and IOC-expired orders only exist in /orders/history, so check both. Prediction is the same drill on /api/v1/prediction/me/positions?marketId=… and /api/v1/prediction/me/orders?marketId=…&limit=50 (that one carries every status, filled included; PM share counts are sharesE6 micro-units).
Then report what the account actually shows — the new position size and entry plus the two exit levels now attached to it, or "resting on the book, nothing filled yet". A position that did not move and no order row means the order did NOT land: say that, never "order placed". Same after a close or a cancel — the position must really be gone (or smaller), the order really out of /orders.
Rules that prevent losses
- **Every perp position carries a take-profit AND a stop-loss. Both, or
no entry.** Decide the two levels before you place anything. Enter with the bracket advanced order when you can — entry, TP and SL in one signed call, so no window exists where the position is bare; plan.py sends nothing else for a perp leg — otherwise attach them in the same turn the entry fills, before you report it: POST /api/v1/perp/positions/{market}/tpsl {"take_profit_price": "…", "stop_loss_price": "…"}. The endpoint accepts one side alone; one side alone is not protection, so send both. Then read the position back and confirm takeProfit and stopLoss are both non-null. Two exemptions, and only these: an order that reduces or closes an existing position, and a side already covered by a live bracket/OCO leg — that one answers POS_TPSL_EXISTS (14005) and is already protected, so leave it alone rather than firing replace: true at it. If the user will not name a stop, do not place the entry; tell them the level you would have used and let them decide. Prediction positions have no equivalent engine — say so plainly instead of implying an exit is attached.
- **Omitting
leverageon a perp order uses your per-market preference,
else 20x** (clamped to the market max; before 2026-08-29 it meant the market MAXIMUM). Set it explicitly on every order anyway — the response echoes the value applied.
price/sizeare JSON strings, and the TPSL / batch-cancel / leverage
bodies are snakecase** (`takeprofitprice`, `orderids, position_side). A camelCase key there is silently ignored and the call still returns 200 — TPSL comes back takeProfit: null, batch cancel cancelledCount: 0`. Read the position / count back after each call.
- **Off-session markets cap new risk at 2x leverage and 1,000 USDC
notional** — armed when a market's price is on the fallback feed or its content has gone stale (equity perps outside their session). Over either: 400 REQ_INVALID_PARAMS on leverage or qty. It applies to the 11 advanced order types as well, measured on the algo's total size, and reduce-only is exempt only when a real position backs it.
- Prediction `priceE6` lives on a 0.1¢ grid: a multiple of 1000,
inside [1000, 999000]. Off-grid → 400 REQ_INVALID_PRICE.
- Prediction routes are typed: binary markets on
/api/v1/prediction/orders, multi-outcome on /api/v1/prediction/multi-outcome/orders; a mismatch is rejected. Cancels are unified — and they are DELETE with a JSON body (the client signs it correctly).
- Perp orders are rejected past 15% from mark/index, and this fires
BEFORE the balance check — a far-from-market resting limit comes back 400 TRADE_PRICE_DEVIATION, not "insufficient funds". Quote inside the band or use a market order.
- Prediction BUY orders need ~1 USDC notional (
amount x priceE6, with a
one-share tolerance). Below it: 400 REQ_INVALID_PARAMS on amount. Sells have no minimum — a dust position can always be closed.
- Always pass
clientOrderId(1-64 chars[A-Za-z0-9_-]) so retries are
idempotent instead of duplicate orders.
- Keys default to
canTrade: falseand can carry market allowlists — a
403 PERM_* means the key, not the request.
Canonical docs
This file is a wrapper; the skill manual is the product. Before first use of an area beyond the quick reference (funding, TP/SL, advanced orders, treasury…), fetch the relevant note as raw markdown from https://www.1024ex.com/skills/raw/<path>.md — pick <path> straight from the directory below, no index fetch needed. Complete corpus: https://www.1024ex.com/llms-full.txt · index: https://www.1024ex.com/llms.txt · graph: https://www.1024ex.com/skills.json
<!-- note-directory:begin — generated by scripts/gen-skill-index.mjs; do not edit by hand -->
- 00-quickstart/claim-testnet-usdc — POST /testnet/faucet/claim — fund your own testnet account with one signed call, no browser, no source-chain deposit.
- 00-quickstart/sign-requests — HMAC-SHA256 request signing — the three headers every authenticated call must carry.
- 10-discover/funding-and-prices — Funding rate current/list/history, mark & index price, open interest, insurance fund. Public.
- 10-discover/options-chain — Options discovery — catalog, contract detail, expiries, the priced chain with Greeks, book and tape. Public, no auth. Every number is an e6 integer, and every "not found" answers empty instead of 404.
- 10-discover/perp-markets — Perp market discovery — list, detail, ticker, orderbook, trades, klines. Public, no auth.
- 10-discover/prediction-collections — Event groupings — one tournament or series is a collection of related binary/multi-outcome markets.
- 10-discover/prediction-discovery — Find markets from a keyword — unified search (perps + collections + markets) plus the filtered PM list, shelves, categories and tags.
- 10-discover/prediction-market-data — Per-market PM data — detail, outcomes, orderbook/depth with the LP virtual ladder, prices, klines, trades, media.
- 10-discover/watchlists — Cross-product watchlists — perp/PM items with stance; share, clone, community. Same lists the web app shows.
- 16-strategies/backtest — Upload a strategy (or a new version of it) and run it on 1024's hosted backtester — the strategy object, the run, the result fields and their units (
dataRangeper market), the universe endpoint (60 markets — 30 crypto + 30 US equities — on Massive 5m / 1d bars over the fixed year 2025-09-18 → 2026-09-18; every other perp live-only), the engine's fill assumptions, quotas, and what the sandbox does and does not isolate. - 16-strategies/deploy-and-monitor — Run an uploaded strategy on 1024's runner — paper against a virtual balance, or live on a sub-account funded from main with its own key — then read its state, tail its log and stop it. Stop cancels, closes and sweeps back to main by default.
- 16-strategies/write-a-strategy — The file 1024's hosted runner executes — one
Strategysubclass inmain.py, numpy for the maths, two kinds — time-series (one market,on_barevery closed bar,closes/ohlcv) and cross-sectional (a basket,rebalance_every,on_rebalancereturning target weights offpanel) —pct=and weights off equity with no leverage, a take-profit and stop-loss after every entry. 60 markets backtest — 30 crypto + 30 US equities / ETFs on Massive 5m / 1d bars over 2025-09-18 → 2026-09-18, every other perp live-only —interval()5m–1d for either kind — and the equity-session traps. - 20-trade/advanced-orders — 11 perp algo order types — conditional, twap, vwap, scale, oco, bracket, iceberg, pegged, pov, trailing-stop, sniper.
- 20-trade/close-position — Close a perp position full or partial. Market by default; type=limit is an IOC at your price — no_fill leaves the position untouched and rests nothing.
- 20-trade/leverage-and-margin — Read/set per-market leverage and add/remove position margin. Request bodies are snake_case here.
- 20-trade/manage-orders — List, fetch, cancel perp orders — single, batch of 50, or cancel-all. DELETEs carry JSON bodies.
- 20-trade/mint-redeem-claim — USDC to complete-set mint, redeem, claim winnings/refunds, settlement sweep — binary and multi-outcome.
- 20-trade/options-orders — Place, list and cancel options orders. e6 integers not decimal strings,
orderTypenottype,clientOrderIdmandatory, cancel is a POST — almost nothing carries over from the perp order path. - 20-trade/order-plans — The one link that gets an order placed — publish a basket of bracket legs as a hosted page (signed, or unsigned as a draft), let the user sign in, fund and click there, and read
stageback. No key required from the agent, none ever from the user. - 20-trade/place-perp-order — POST a perp order, limit or market. camelCase body; price/size are strings. Omitted leverage = your per-market preference, else 20x — no longer the market max.
- 20-trade/prediction-orders — Place and cancel PM orders — binary vs multi-outcome routes, numeric-TIF wire quirk, unified DELETE cancels.
- 20-trade/tpsl — Attach, modify, cancel market-priced take-profit / stop-loss on a perp position. snake_case body.
- 30-portfolio/account-overview — Equity, cash, locks, margin ratios and risk level in one call — plus perp margin, 30d stats, token holdings.
- 30-portfolio/balances — Token balances — available vs locked per token, USDC-valued, all tokens or one symbol.
- 30-portfolio/history — Every look-back surface — perp orders and trades, funding, liquidations, ADL, position history v2, activity.
- 30-portfolio/my-prediction-data — Your PM orders, positions, trades, stats and match/activity feeds — integer shares vs sharesE6 units.
- 30-portfolio/options-positions — Open options positions, manual American exercise, and the exercise/settlement ledger. Exercise is irreversible, idempotency-keyed, and gated on price freshness.
- 30-portfolio/pnl — Perp PnL summary — realized, live unrealized, funding and fees, netted overall and per market.
- 30-portfolio/positions — Open perp positions — all or per market — entry/mark/liq prices, uPnL, margin, ADL rank.
- 40-treasury/deposit — Fund the account — hand over the /deposit link (USDC in the login wallet, other crypto via a one-time address, or card / bank), then confirm the credit landed.
- 40-treasury/deposit-address — A deposit address made for this account right in the chat, for money on an exchange or another chain (USDT on Tron, BTC, ETH, USDC elsewhere). Relay converts it to USDC in the user's own wallet; one tap on 1024 moves it in.
- 40-treasury/internal-transfer — Move USDC between your main account and its subs — direction is fixed by which key signs.
- 40-treasury/sub-accounts — One atomic call creates a sub-account plus its own trading API key, optionally pre-funded from the parent.
- 50-risk-and-keys/api-key-lifecycle — Introspect, list, rotate, and revoke API keys, and the per-key permission model.
- 50-risk-and-keys/error-model — One envelope for every response; code registry highlights, HTTP mapping surprises, and retry rules per class.
- 50-risk-and-keys/idempotency — clientOrderId semantics per domain, PM dedup keys, and how the HMAC replay window shapes safe retries.
- 70-analytics/leaderboards — Trading championships — list, detail, ranked leaderboard, top3, plus your own rank (the only signed call).
- 90-recipes/agent-fleet — One sub-account per strategy — isolated balances, own API keys, one-call kill switch.
- 90-recipes/funding-scanner — Sweep funding rates across every perp market, rank extremes, harvest the carry.
- 90-recipes/liquidation-guard — Watch margin ratio in real time, de-risk automatically before the engine does it for you.
- 90-recipes/market-maker-loop — Quote both sides, stay inside rate budgets, requote on book deltas, cancel clean on exit.
- 90-recipes/one-key-lifecycle — One ETH private key → account → funds → trades → withdrawal. The complete journey, no browser.
- 90-recipes/pm-basket — Build and execute a multi-market prediction basket — discover, price, then IOC each leg.
<!-- note-directory:end -->
