> ## Documentation Index
> Fetch the complete documentation index at: https://docs.upsidemax.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /exchange: Write Request Structure and Format

> Understand the envelope structure of POST /exchange requests — action, signature, and nonce fields for all state-changing operations on Upside .

All state-changing operations on Upside — placing orders, cancelling orders, registering accounts, adjusting margin, and more — use a single endpoint: `POST /exchange`. The operation to perform is determined entirely by the `action.type` field inside the JSON body, not by the URL. This action-based routing means your HTTP client only ever needs to know one write URL; you change the payload to change the operation.

## Endpoint

```text theme={"system"}
POST /exchange
Content-Type: application/json
```

## Envelope Structure

Every `POST /exchange` request body is a JSON object with the following top-level fields:

```json theme={"system"}
{
  "action": {
    "type": "<actionType>",
    "<field>": "<value>"
  },
  "signature": {
    "r": "0x<64 hex>",
    "s": "0x<64 hex>",
    "v": 27
  },
  "nonce": 1778572951477
}
```

### Fields

<ParamField body="action" type="object" required>
  The operation payload. Must contain a `type` string that identifies the action (e.g. `"order"`, `"cancel"`, `"registerAccount"`). All other fields are action-specific.
</ParamField>

<ParamField body="action.type" type="string" required>
  Identifies which action to perform. It also selects the EIP-712 signing path — funds/permission actions use a typed struct, everything else uses the Agent path. See [Authentication](/guide/authentication).

  Common values: `order`, `cancel`, `cancelByCloid`, `modify`, `registerAccount`, `updateLeverage`, `updateIsolatedMargin`.
</ParamField>

<ParamField body="signature" type="object" required>
  EIP-712 ECDSA signature (secp256k1) over the action. The server recovers the signer's Ethereum address from this signature to authorize the operation — there are no API keys.
</ParamField>

<ParamField body="signature.r" type="string" required>
  The `r` component of the ECDSA signature. Must be a `0x`-prefixed lowercase hex string representing a 32-byte value (66 characters total).
</ParamField>

<ParamField body="signature.s" type="string" required>
  The `s` component of the ECDSA signature. Same format as `r`.
</ParamField>

<ParamField body="signature.v" type="integer" required>
  The recovery parameter. Must be `27` or `28` (Ethereum convention: `27 + recovery_bit`).
</ParamField>

<ParamField body="nonce" type="integer" required>
  An int64 Unix millisecond timestamp. Must be unique per signer. Used as replay protection — the server rejects any previously seen nonce from the same address.
</ParamField>

<ParamField body="vaultAddress" type="string">
  Optional. The Ethereum address of a vault for which the signer is acting as a proxy. When present, the server verifies that the signer is an authorized agent of the vault and applies the operation to the vault's account.
</ParamField>

<ParamField body="inviteCode" type="string">
  Conditional. A 6-character alphanumeric invite code required by `registerAccount` in gated environments. Include this field at the top level of the envelope — **not** inside `action`. This field is **not** included in the signed message.
</ParamField>

## Action-Based Routing

<Note>
  Unlike a traditional REST API where `POST /orders` creates an order and `DELETE /orders/:id` cancels one, Upside DEX routes every write operation through `POST /exchange`. Routing is determined by `action.type` in the body. This keeps the transport layer simple and makes it easy to batch operations in a single request structure.
</Note>

The table below maps `action.type` values to their operations:

| `action.type`          | Operation                                       |
| ---------------------- | ----------------------------------------------- |
| `registerAccount`      | Register a new trading account for an address   |
| `order`                | Place one or more orders (up to 10 per request) |
| `cancel`               | Cancel one or more orders by order ID           |
| `cancelByCloid`        | Cancel an order by client order ID              |
| `modify`               | Modify the price or size of an existing order   |
| `updateLeverage`       | Change leverage for an asset                    |
| `updateIsolatedMargin` | Add or remove isolated margin for a position    |

## Example Request

The following example places a limit GTC buy order for 10 units of SOL1 at price 50:

```json theme={"system"}
{
  "action": {
    "type": "order",
    "orders": [
      {
        "a": 1,
        "b": true,
        "p": "50",
        "s": "10",
        "r": false,
        "t": { "limit": { "tif": "Gtc" } }
      }
    ],
    "grouping": "na"
  },
  "signature": {
    "r": "0x3b2a1f...",
    "s": "0x7cf133...",
    "v": 28
  },
  "nonce": 1778572951477
}
```

See [Authentication](/guide/authentication) for instructions on building the signature, and [Nonce](/guide/nonce) for nonce generation rules.
