Skip to main content
Every write operation on UpsideMAX — placing orders, cancelling positions, adjusting margin, managing collateral, and configuring your account — is submitted through a single endpoint: POST /exchange. The server inspects the action.type field in the request body to determine which operation to execute, then recovers your wallet address from the accompanying ECDSA signature to authorize it. This unified design means you only need one integration point for all state-changing calls.

Endpoint

Request Envelope

Every request shares the same top-level envelope structure:
sync, signatureChainId, and action-specific envelope fields (such as inviteCode for registerAccount) sit alongside action, signature, and nonce — not inside action — and are not included in the signed payload. Switching sync therefore requires no change to your signing code.

Authentication

All requests require a valid ECDSA signature. The server recovers your wallet address from the (r, s, v) tuple and uses it to authorize the operation — no API key header is needed. See the Authentication guide for details on what to sign and how to construct the signature.
Use the exact action.type strings listed below. They are the complete set — an unrecognised value returns UNKNOWN_ACTION. Placing an order is order, not newOrder, createOrder or placeOrder; cancelling is cancel. Do not infer an action name from a method name in an SDK or from another exchange’s API.

Action Groups

Account

Register your wallet and enroll in market deployers.

Orders

Place, modify, and cancel perpetual orders.

Margin & Leverage

Adjust margin mode, leverage, and isolated margin balances.

Conditional Orders

Set and cancel take-profit, stop-loss, and other conditional orders.

API Wallets

Delegate signing to agent wallets.

All Available Actions

Account

Orders

Margin & Leverage

Conditional Orders

Collateral

API Wallet

Response Shape

A request that is processed synchronously returns HTTP 200 with "status": "ok". The action’s result is inside response.data, except for registerAccount, which places accountId directly under response.
"status": "ok" indicates the request was received and processed — it does not guarantee the business operation succeeded. Order and cancel actions report each item in response.data.statuses[]; the other actions embed an errorCode (number) and errorMessage inside response.data when the request is refused. Always check those fields after an HTTP 200.

Error responses

A request rejected before processing returns a non-2xx HTTP status with "status": "error":
A parameter that fails validation returns HTTP 400 with code INVALID_PARAM and an errors[] array with one entry per failing field. Such a request is not executed.

Synchronous and asynchronous responses

order, cancel, cancelByCloid, cancelAll, and modify support two response forms, selected per request by the top-level envelope field sync. Both forms submit the same transaction and produce the same outcome; only the HTTP answer differs. Set sync explicitly whenever you need a predictable form — an omitted sync follows the server default, which is not guaranteed to be identical across environments. The 202 body is identical for all five actions: type is the literal "accepted", and count is always 1 — it acknowledges the request, not the number of orders or cancels it carried. The 200 body depends on the action: Constraints:
  • Only these five actions accept sync. Every other action always answers synchronously; a sync field in its envelope — true or false — returns 400 SYNC_NOT_APPLICABLE.
  • sync must be a JSON boolean. A string such as "true" or a number returns 400 BAD_REQUEST.
  • Synchronous requests occupy server capacity while they wait. Under load the server may return 503 DOWNSTREAM_UNAVAILABLE; sending the request with sync: false and reading the result from WebSocket avoids it.

Timeouts and retries

A synchronous request that does not receive its result within the server’s waiting window returns 504 DOWNSTREAM_TIMEOUT. A 504 does not mean the request failed — the action may already have been executed. The same nonce is executed at most once per signing address. Re-sending an identical signed envelope therefore cannot execute the action twice: while the first copy is still in flight it returns 400 DUPLICATE_NONCE, and once the first copy is processed a re-send cannot return its result either. Neither answer tells you whether the first attempt executed. After a 504, a network error, or any other unknown outcome:
1

Do not sign again with a fresh nonce yet

A new nonce makes a new request. If the first one executed, a new signature executes the action a second time.
2

Reconcile by query

Look the request up by its effect: userOrders for orders still resting, orderHistory and userFills for orders that already ended, or the orderUpdates channel. Correlate orders by your client order ID c. For margin and collateral actions, read the resulting state from userAccount.
3

Retry only what did not execute

Once you have confirmed the action did not execute, sign it again with a new nonce and submit it.

HTTP errors

The codes below apply across POST /exchange. Each action page lists the ones that action can return; Error Codes carries the full reference.