> For the complete documentation index, see [llms.txt](https://www.aevo.xyz/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.aevo.xyz/docs/api-reference/subaccounts.md).

# Subaccounts

A subaccount is a separate trading account owned by a main account. It has its own address, balances, positions, orders and margin. For how subaccounts work in the app, see [Subaccounts](/docs/aevo-products/aevo-exchange/subaccounts.md).

**Subaccounts don't have their own API keys or signing keys.** You trade every subaccount with your **main account's** API key and signing key, and each request names the subaccount it acts for. One key set covers the main account and all of its subaccounts.

## How it works

1. **Create** a subaccount from the main account. See [Creating subaccounts](/docs/api-reference/subaccounts/creating-subaccounts.md).
2. **Select** the subaccount on each request: the `AEVO-SUBACCOUNT` header on REST, or the `subaccount` field when you authenticate on the websocket.
3. **Sign orders** with the main account's signing key, with `maker` set to the subaccount's address.

For a step-by-step walkthrough with complete REST and websocket code, see [Trading with a subaccount](/docs/api-reference/subaccounts/trading-with-subaccounts.md).

## Endpoint map

| Step                                     | Endpoint                                                                                         | Called with                            | Signature needed                                                                           |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------------------------------------------ |
| List subaccounts, balances and positions | [`GET /subaccounts`](/docs/api-reference/urls/private-api/getsubaccounts.md)                     | Main account API key (read-only works) | —                                                                                          |
| Create a subaccount                      | [`POST /subaccounts`](/docs/api-reference/urls/private-api/postsubaccounts.md)                   | Main account API key                   | Main wallet or signing key (`CreateSubaccount`), and the subaccount key (`LinkSubaccount`) |
| Rename a subaccount                      | [`POST /subaccounts/rename`](/docs/api-reference/urls/private-api/postsubaccountsrename.md)      | Main account API key                   | —                                                                                          |
| Archive an empty subaccount              | [`POST /subaccounts/archive`](/docs/api-reference/urls/private-api/postsubaccountsarchive.md)    | Main account API key                   | —                                                                                          |
| Trade, read and cancel as a subaccount   | Any private endpoint, with `AEVO-SUBACCOUNT`                                                     | Main account API key                   | Main signing key, with `maker` = subaccount                                                |
| Move funds out of a subaccount           | [`POST /transfer`](/docs/api-reference/urls/private-api/posttransfer.md), with `AEVO-SUBACCOUNT` | Main account API key                   | Subaccount key (`Transfer`)                                                                |

## Acting as a subaccount over REST

Add the `AEVO-SUBACCOUNT` header with the subaccount's address to any private request. The request then reads and acts on the subaccount instead of the main account.

```json
"AEVO-KEY": `[Insert main account API key]`
"AEVO-SECRET": `[Insert main account API secret]`
"AEVO-SUBACCOUNT": `[Insert subaccount address]`
```

* Use the **checksummed** subaccount address, for example `0xAbC…`, exactly as `GET /subaccounts` returns it.
* Without the header, the same key acts on the main account.
* A read-only API key stays read-only for subaccounts, and the key's IP allowlist still applies.

### With HMAC signatures

When you authenticate with a signature, the subaccount is part of the signed message. Append it as a sixth field:

```
message = apiKey,timestamp,httpMethod,path,body,subaccount
```

Requests without the header keep the usual five-field message. See [Authentication](/docs/api-reference/urls/authentication.md) for the base format.

```python
import os
import time
import hmac
import hashlib
import requests

API_KEY = os.environ["API_KEY"]        # main account
API_SECRET = os.environ["API_SECRET"]  # main account
SUBACCOUNT = "0xYourSubaccountAddress"


def get_headers(path, method, body, subaccount=None):
    timestamp = str(time.time_ns())
    fields = [API_KEY, timestamp, method.upper(), path, body]
    if subaccount:
        fields.append(subaccount)
    signature = hmac.new(
        API_SECRET.encode("utf-8"), ",".join(fields).encode("utf-8"), hashlib.sha256
    ).hexdigest()

    headers = {
        "AEVO-TIMESTAMP": timestamp,
        "AEVO-SIGNATURE": signature,
        "AEVO-KEY": API_KEY,
    }
    if subaccount:
        headers["AEVO-SUBACCOUNT"] = subaccount
    return headers


# The subaccount's balances and positions
headers = get_headers("/account", "GET", "", SUBACCOUNT)
print(requests.get("https://api-testnet.aevo.xyz/account", headers=headers).json())
```

## Acting as a subaccount over the websocket

A websocket connection acts as one account at a time. Add `subaccount` to your authentication to bind the connection to that subaccount. Open one connection per account if you trade several at once.

**Per-connection authentication**

```jsonc
{
  "op": "auth",
  "data": {
    "key": `[Insert main account API key]`,
    "secret": `[Insert main account API secret]`,
    "subaccount": `[Insert subaccount address]`
  }
}
```

**One-off signed authentication.** Add `subaccount` to `data` and append it to the signed message. The `data` field of the signed message is empty for `auth`, so there are two commas before the subaccount:

```
message = apiKey,timestamp,ws,auth,,subaccount
```

**Per-message authentication.** Add `subaccount` to the `auth` object and append it to the signed message:

```
message = apiKey,timestamp,ws,op,data,subaccount
```

Private channels (orders, fills, positions) then stream the subaccount's data. See [Websocket authentication](/docs/api-reference/websocket-api/private-operations/websocket-authentication.md) for the base formats.

## Signing orders for a subaccount

Orders use the usual `Order` type (see [Signing Orders](/docs/api-reference/signing-orders.md)), with two differences:

* `maker` is the **subaccount's** address.
* Sign with the **main account's** signing key. The main wallet itself also works.

Because the subaccount's address is inside the signed order, a signature for one subaccount can't be reused for another. Send the order with the `AEVO-SUBACCOUNT` header, or over a websocket connection bound to the subaccount.

RFQ quotes work the same way: `maker` is the subaccount, signed by the main account's signing key.

## Moving funds

| From              | To                                          | Allowed |
| ----------------- | ------------------------------------------- | ------- |
| Main account      | One of its subaccounts                      | Yes     |
| Any other account | A subaccount                                | No      |
| Main account      | Any other Aevo account, or a withdrawal     | Yes     |
| Subaccount        | Its main account                            | Yes     |
| Subaccount        | Another subaccount of the same main account | Yes     |
| Subaccount        | Any other account                           | No      |
| Subaccount        | Withdrawal (any destination)                | No      |

A transfer out of a subaccount is signed with the **subaccount's own key** (the `Transfer` type, with `account` set to the subaccount), not the main signing key. If you create subaccounts as described in [Creating subaccounts](/docs/api-reference/subaccounts/creating-subaccounts.md), you can re-derive that key from your main wallet at any time.

Subaccounts can never withdraw. To withdraw, transfer to the main account and withdraw from there.

Deposit to the main account, then transfer to a subaccount. On-chain deposits made directly to a subaccount's address can't be refused and are credited to it; move them to the main account with a transfer.

## Shared rules

* **Rate limits** are shared by a main account and its subaccounts. Adding subaccounts doesn't increase your limits. See [Rate Limits](/docs/api-reference/rate-limits.md).
* **Fees** come from the main account: maker/taker fees, fee tier, staking discount and custom fees.
* **Margin and liquidation** are per account. Each subaccount has its own margin, leverage and margin mode settings.
* **Self-trade prevention** covers the whole family. A main account and its subaccounts, or two subaccounts of the same main account, never fill against each other. By default the incoming (taker) order is cancelled; an explicit `EXPIRE_MAKER` or `EXPIRE_TAKER` setting is honored. This applies to RFQ / block trades too.
* **Builders.** A subaccount can approve builders and place builder orders, but it can't register a builder. [`POST /builder/register`](/docs/api-reference/urls/private-api/postbuilderregister.md) as a subaccount returns `SUBACCOUNT_BUILDER_NOT_ALLOWED`.
* **Referrals** don't apply to subaccounts. They can't use, own or claim referral codes or rewards.
* **Restrictions** on the main account apply to all of its subaccounts.

## Errors

| Error                                | When                                                                                                                                                                  |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SUBACCOUNT_NOT_FOUND`               | The `AEVO-SUBACCOUNT` address isn't an active subaccount of the authenticated main account.                                                                           |
| `SUBACCOUNT_ARCHIVED`                | The subaccount is archived.                                                                                                                                           |
| `SUBACCOUNT_TRANSFER_OUTSIDE_FAMILY` | A transfer with a subaccount on either side crossed families: a subaccount can only send to, and receive from, its main account and that account's other subaccounts. |
| `SUBACCOUNT_WITHDRAW_NOT_ALLOWED`    | A subaccount tried to withdraw. Transfer to the main account first.                                                                                                   |
| `SUBACCOUNT_BUILDER_NOT_ALLOWED`     | A subaccount tried to register a builder.                                                                                                                             |
| `SUBACCOUNT_REFERRAL_NOT_ALLOWED`    | A subaccount tried to use, own or claim a referral.                                                                                                                   |
| `SUBACCOUNT_CLAIM_NOT_ALLOWED`       | A subaccount tried to claim a reward that is paid to the main account.                                                                                                |

Errors about the `AEVO-SUBACCOUNT` header are only returned after the request is fully authenticated. For creation errors, see [Creating subaccounts](/docs/api-reference/subaccounts/creating-subaccounts.md#errors).

## Environments

|           | Mainnet                | Testnet                        |
| --------- | ---------------------- | ------------------------------ |
| REST      | `https://api.aevo.xyz` | `https://api-testnet.aevo.xyz` |
| Websocket | `wss://ws.aevo.xyz`    | `wss://ws-testnet.aevo.xyz`    |
| App       | `https://app.aevo.xyz` | `https://testnet.aevo.xyz`     |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://www.aevo.xyz/docs/api-reference/subaccounts.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
