For production or low-latency trading, use the WebSocket track — the primary interface. Requests target testnet (
https://api.testnet.arcus.xyz); new accounts start empty — fund yours with the Testnet Deposit button (~$1,000), or an on-chain deposit for more. See Authentication for signing.Step 1: Install
Only published libraries — no Arcus package required.Step 2: Get an API key
Your API key is an Ed25519 keypair; the server stores only the public half, and the key is registered to your wallet by a one-time EIP-712 typed-data signature (eth_signTypedData_v4) — see POST /v1/createApiKey for the domain and types (the legacy EIP-191 scheme is deprecated but still accepted during the migration window). The Arcus web app does all of this for you and is the quickest way to get a key; you can also do it entirely in code.
Option A — Generate on the web app (recommended)
- Open the API Keys page — testnet, or mainnet for production — and connect the wallet you’ll trade from.
- Enter a name and click Generate. The app creates the keypair in your browser.
- Copy the API Signing Key now — it’s the private half, shown once, and cannot be recovered. Pick a Subaccount # (default
0) and Days Valid (up to 180), then click Authorize and confirm the signature in your wallet.
wallet.address; with a web-app key, use your wallet_address wherever you see it.
Option B — Generate in code
Generate a fresh keypair and register it with onecreateApiKey call — the same operation the web app performs:
Step 3: Place an order
Order requests sign a typed canonical payload — the compact, key-sorted JSON object shown below is the signing message (no prefix). The timestamp is carried inside asct and must equal the X-Timestamp header (Unix nanoseconds). Price and size are signed as integer ticks and quantums, so you first convert them with the market’s tickSize / stepSize. See Authentication for the full field reference.
placeOrder, cancelOrder, and modifyOrder use the typed payload above; cancelAllOrders and setLeverage use the legacy timestamp + action + canonicalJSON(body) message — see Authentication.
In the request body,
quantity and price stay decimal strings (not floats). The integer q/p in the signed payload are derived from them via tickSize / stepSize; the two must agree, so reuse the same values.Market orders must use
timeInForce: IOC (other values are rejected with must be IOC for MARKET orders) and still carry a price — it acts as a protective slippage bound that must be within 10% of the current mark price (for TPSL market orders, within 10% of the trigger price), or the order is rejected. Because of this bound a MARKET order behaves like a marketable limit order, so many integrations simply send an aggressive LIMIT order instead.Step 4: Place a batch
batchPlaceOrders signs each order individually with its own typed payload, all sharing one X-Timestamp (used as each element’s ct). The X-API-Key + X-Timestamp headers authenticate the batch and each order carries its own signature. The X-Signature header must still be present — set it to any one element’s signature (the batch is verified per element, not against this header).
batchCancelOrders works the same way — each element signs its own cancelOrder payload (op 2).
Next steps
Order placement is asynchronous — the response acknowledges receipt, and the order’s lifecycle (fills, cancels) streams on theorders and userFills WebSocket channels. To follow orders in real time, move to the WebSocket track.