Overview
Endpoint
Mainnet REST Endpoint
Spot:
https://mainnet-gw.sodex.dev/api/v1/spotPerps:
https://mainnet-gw.sodex.dev/api/v1/perps
Mainnet WebSocket Endpoint
Spot:
wss://mainnet-gw.sodex.dev/ws/spotPerps:
wss://mainnet-gw.sodex.dev/ws/perps
Testnet REST Endpoint
Spot:
https://testnet-gw.sodex.dev/api/v1/spotPerps:
https://testnet-gw.sodex.dev/api/v1/perps
Testnet WebSocket Endpoint
Spot:
wss://testnet-gw.sodex.dev/ws/spotPerps:
wss://testnet-gw.sodex.dev/ws/perps
Key terminology
The docs overload the word "key" in several ways. This table pins the meanings down once; later sections assume these definitions.
Master wallet
The EVM wallet that owns the Sodex account. Deposits and addAPIKey / revokeAPIKey must be signed by this wallet.
EVM address 0xAbC...123
Master wallet private key
The 32-byte ECDSA private key of the master wallet. Holding it grants full control of the account, so it should stay offline and be used only for the one-time addAPIKey setup and for revocation.
0x1234...cdef (32 bytes, hex)
API key
A named, revocable signing credential attached to the master account (or a sub-account) via addAPIKey. Each master account can hold up to 5 API keys. API keys are for signing trading actions — they cannot query account data. Using an API key (rather than the master wallet) for day-to-day trading is the recommended workflow.
a row with name="api-key-01", publicKey=0x3d45...8256
API key name
The human-readable string that identifies one API key. Must match ^[0-9a-zA-Z_-]{1,36}$ and cannot be default. Passed in the X-API-Key HTTP header (despite the header's name, the value is the key name, not a public key or private key).
"api-key-01"
API key public key
The EVM address registered for that API key. Stored on-chain when you call addAPIKey and also echoed in query responses.
0x3d4595c8742d0a58173a9963c05755b59a8f8256
API key private key
The 32-byte ECDSA private key whose public address matches the API key's public key. Held by the client; used to sign every request that presents that API key's name in X-API-Key.
0xabcd...7890 (32 bytes, hex)
Which key signs what
addAPIKey / revokeAPIKey
Master wallet
Master wallet's private key
All other trading actions (e.g. newOrder, cancelOrder, transferAsset)
A registered API key
That API key's private key
Recommended workflow: use the master wallet's private key only to register and revoke API keys. For all normal trading requests, sign with a dedicated API key's private key. This lets you keep the master wallet offline and rotate signing credentials without moving funds.
Header naming caveat — the HTTP header X-API-Key carries the name of the key, not the key value. The corresponding private key is used to produce X-API-Sign; the private key itself is never sent over the wire.
API keys and nonces
API keys
A master account can approve or revoke API keys to sign on behalf of the master account or any of the sub-accounts. Each master account can have at most 5 API keys.
Sodex currently supports EVM addresses as API key public keys. The client holds the API key's private key and uses it to sign each request; the server verifies the signature against the API key's registered public key.
API keys are only used to sign. To query account data associated with a master or sub-account, pass the actual accountID of that account — API keys are not lookup identifiers. See Get account ID for how to retrieve your account ID.
Sodex nonces
Similar to Hyperliquid, on Sodex the 100 highest nonces are stored per signing address. Every new transaction must have a nonce larger than the smallest nonce in this set and must never have been used before.
Nonces are tracked per signing address:
For trading actions, this is the API key's public key (EVM address) — the one you registered via
addAPIKey.For
addAPIKey/revokeAPIKey, this is the master wallet's address, which has its own independent nonce counter.
Nonces must be within (T - 2 days, T + 1 day), where T is the Unix millisecond timestamp on the block of the transaction.
The following steps may help port over an automated strategy from a centralized exchange:
Use a separate API key per trading process. Nonces are tracked per signing address (see above), so two sub-accounts that both sign with the same API key share a single nonce tracker — concurrent strategies on each sub-account will race on the nonce. Create one API key per sub-account to avoid this.
The trading logic tasks send orders and cancels to the batching task.
For each batch of orders or cancels, fetch and increment an atomic counter that ensures a unique nonce for the address. The atomic counter can be fast-forwarded to current Unix milliseconds if needed.
This structure is robust to out-of-order transactions within 2 seconds, which should be sufficient for an automated strategy geographically near an API server.
Typed signature
In Sodex, we use EIP712 for Typed structured data hashing and signing. We use different domains for different actions.
Trading actions
For mainnet use 286623 for domain.chainId, for testnet use 138565 for domain.chainId. For spot actions, use spot for domain.name and for perps actions, futures for domain.name.
After you get the signature bytes sig, append byte 1 before the sig bytes to get typed signature. For example, your signed signature is 0x789a6bcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab, the correct typed signature is 0x01789a6bcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab.
How to compute payloadHash
payloadHashpayloadHash = Keccak256(json.Marshal(payload))
The payload is a JSON object with two fields:
For spot:
typeis one of"newOrder","cancelOrder","transferAsset","scheduleCancel","revokeAPIKey", and more.For perps:
typeis one of"newOrder","cancelOrder","updateLeverage","updateMargin","updateCollateral"(testnet only),"transferAsset","scheduleCancel","revokeAPIKey", and more.
You must use your private key of the master account to sign revokeAPIKey action.
Important rules for producing a correct payloadHash:
Compact JSON — no whitespace or newlines. Use
json.Marshalin Go, orJSON.stringifywithout extra arguments in JavaScript.Key order must match the Go struct field order — the server verifies signatures by parsing the request body into Go structs and re-marshaling via
json.Marshal, which serializes fields in struct definition order. If your JSON keys are in a different order, the hash will differ and signature verification will fail.Refer to the struct definitions in sodex-go-sdk-public for the authoritative field order.
For example,
PerpsOrderItemfields must appear in this order:clOrdID,modifier,side,type,timeInForce,price,quantity,funds,stopPrice,stopType,triggerType,reduceOnly,positionSide.
DecimalStringfields are JSON strings, not numbers — fields typed asDecimalStringin the schema (e.g.price,quantity,funds,stopPrice) must be serialized as quoted strings in the signing payload (e.g."quantity":"0.001", not"quantity":0.001). The HTTP request body uses the same format.omitemptyfields must be omitted when unset — optional pointer fields in the Go struct (those withjson:",omitempty") must not appear in the JSON when they have no value. Non-optional fields (e.g.modifier,reduceOnly,positionSide) must always be present, even with zero values.
Example — perps market buy order signing payload:
Note: the HTTP request body contains only the params object (without the type wrapper), using the same field order and types as the signing payload.
End-to-end signing example
Signing a newOrder action with a registered API key, end-to-end.
Prerequisite: you have already called
addAPIKey(signed by the master wallet — see Add API Key) and hold the API key's private key locally.
Inputs
Steps
Compute
payloadHashas described in How to computepayloadHash.EIP-712-sign the
ExchangeAction{payloadHash, nonce}struct with the API key's private key (0x2222…) under domain{name:"futures", chainId:286623, verifyingContract:0x00…00}.Prepend byte
0x01to the 65-byte signature → this is the value ofX-API-Sign.Send the request with
X-API-Keyset to the name of the API key:
The server looks up the API key named api-key-01 on accountID=12345, recovers the signer address from X-API-Sign, and verifies it equals the API key's registered publicKey (0x3d45…8256).
Common pitfalls
Putting the API key's EVM address (
0x3d45…8256) inX-API-Key— wrong; use thenamestring.Signing the payload with the master wallet's private key — wrong for trading actions; the server verifies against the API key's registered public key and will reject the signature. (Exception:
addAPIKey/revokeAPIKey— those must be signed by the master wallet, since they change the API key set itself.)Forgetting the
0x01prefix — the server rejects un-typed raw 65-byte signatures.
Get account ID
Account IDs are required to query account data and to sign trading actions. Retrieve them via either of:
Via REST API
The aid field in the response is the account ID. By default this is the primary account; pass ?accountID=<id> to query a specific sub-account. The same endpoint is available under ${SPOT_ENDPOINT} for spot.
See WsPerpsState for the full response shape.
Reference Pages
Go SDK Signing GuideAPI Rate LimitsREST API v1WebSocket API v1Last updated