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

# Get Started

A seven-step walkthrough from a cold start to an open position on the Nexus Exchange: sign in with your wallet, mint an HMAC API key, sign requests, fund the account, browse markets, place an order, and monitor positions.

Every step is shown in five clients — cURL, Rust, Python, TypeScript, and the Exchange CLI. Pick a tab per step.

This page began as the **Getting Started** tab of the interactive API docs the Exchange app once served at `/api-docs`. That route no longer resolves — this page is now the guide.

## Before you start

* **You need an Ethereum wallet** to sign the login message. Nothing else is required to begin.
* **Base URL.** The API is served at the Exchange deployment's origin plus `/api/exchange` — the gateway. Examples below use `https://exchange.nexus.xyz/api/exchange`. Running locally, the base is `http://localhost:9090`. Substitute the base for the deployment you are actually calling. Paths are shown with the `/api/v1` prefix where a versioned route exists, since that is the canonical surface — so a full URL reads `https://exchange.nexus.xyz/api/exchange/api/v1/…`. See [Base URLs](/api-reference/readme.md#base-urls) for why the contract's own `servers` override is not usable directly.
* **Authentication.** Two schemes: a **session token** (Bearer) used only to create and manage API keys, and **HMAC-SHA256** API-key signing used for everything else, including all trading.
* **Two surfaces.** The Exchange app is deployed twice from one codebase: a **testnet** surface, which is live and funds accounts from a synthetic-credit faucet, and a **mainnet** real-funds surface, which will be funded by bridging USDX from Ethereum Mainnet. Mainnet is **2026-05-20**. Step 4 below differs between the two — both variants are documented.
* **Placeholders.** Values such as `0xSIGNATURE_HEX`, `nx_7f3a1b...`, `sess_abc123...`, and `0x<wallet-private-key>` are placeholders. Substitute your own; never commit a secret.

### Language coverage

cURL is the canonical, always-populated baseline. The four SDK/CLI clients do not yet cover every step. Where a client has no example for a step, the tab says so and the cURL example above it is the one to follow — the interactive docs behave the same way, falling back to cURL with a note.

### Machine-readable entry points

Everything an agent needs in order to start without reading this page:

* `llms.txt` — <https://exchange.nexus.xyz/llms.txt>
* `openapi.json` — the OpenAPI contract, at `https://exchange.nexus.xyz/api/exchange/openapi.json`
* `/metadata` — the Exchange app's machine-readable metadata route
* **MCP server** — published to npm, so adding it is one line. It runs locally over stdio, which means your API key stays on your machine:

```bash
claude mcp add nexus-exchange -- npx -y @nexus-xyz/exchange-mcp
```

Its public market-data and demo tools need no credentials, so the command is useful before you have a key. A hosted MCP endpoint is planned; its DNS is not live yet, so there is no remote URL to add today.

The OpenAPI spec and changelog are versioned at [nexus-xyz/nexus-exchange-api](https://github.com/nexus-xyz/nexus-exchange-api); releases are tracked on [GitHub Releases](https://github.com/nexus-xyz/nexus-exchange-api/releases).

***

## Authentication

Steps 1–3 get you from a wallet to a signed request.

## 1. Sign in

`POST /auth/login` — no authentication required.

Authenticate with an EIP-191 personal signature. The message to sign is always the fixed string “Sign in to Nexus Exchange” — your wallet address is recovered from the signature.

**Notes**

* Session token expires in 24 hours.
* You only need the session to create and manage API keys — not for trading.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST 'https://exchange.nexus.xyz/api/exchange/auth/login' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "Sign in to Nexus Exchange",
    "signature": "0xSIGNATURE_HEX"
  }'
```

{% endtab %}

{% tab title="Rust" %}

```rust
use nexus_exchange::{Client, Config, EthSigner, Network};

// EIP-191 personal_sign of the fixed login message. The signer
// holds your key only to sign — nothing is written to disk.
let signer = EthSigner::from_hex("0x<wallet-private-key>")?;
let client = Client::new(Config::new(Network::Stable));

let session = client.sign_in(&signer).await?;
println!("signed in as {}", session.address);
// session.token is a SecretString — hand it to
// Config::session_token to authenticate the /keys endpoints.
```

{% endtab %}

{% tab title="Python" %}

```python
from nexus_exchange import Client, EthSigner

signer = EthSigner.from_hex("0x<wallet-private-key>")

with Client() as client:
    session = client.sign_in(signer)  # EIP-191 personal_sign
    print(session.address, session.token)
```

{% endtab %}

{% tab title="TypeScript" %}
Not available in TypeScript yet — use the cURL example.
{% endtab %}

{% tab title="CLI" %}

```bash
export NEXUS_PRIVATE_KEY=0x<your-evm-key>
nexus auth login   # signs EIP-191, stores the session token (mode 0600)
```

{% endtab %}
{% endtabs %}

**Request body**

```json
{
  "message": "Sign in to Nexus Exchange",
  "signature": "0xSIGNATURE_HEX"
}
```

**Response**

```json
{
  "token": "sess_abc123...",
  "address": "0xYOUR_WALLET_ADDRESS"
}
```

## 2. Create API key

`POST /keys` — **Session token required.**

Use the session token to create an HMAC key pair. The secret is shown once — save it immediately.

**Notes**

* You cannot retrieve the secret after this response.
* Keys inherit your account’s tier; per-tier rate limits are reported in the `X-RateLimit-*` response headers.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST 'https://exchange.nexus.xyz/api/exchange/keys' \
  -H 'Authorization: Bearer sess_abc123...' \
  -H 'Content-Type: application/json' \
  -d '{"label": "my-bot"}'
```

{% endtab %}

{% tab title="Rust" %}

```rust
use nexus_exchange::{Client, Config, Network};

// /keys endpoints authenticate with the session token from step 1.
let client =
    Client::new(Config::new(Network::Stable).session_token("sess_..."));

let key = client.create_api_key().await?;
// key.secret is returned once — persist it immediately.
println!("key_id: {}", key.key_id);
```

{% endtab %}

{% tab title="Python" %}
Not available in Python yet — use the cURL example.
{% endtab %}

{% tab title="TypeScript" %}
Not available in TypeScript yet — use the cURL example.
{% endtab %}

{% tab title="CLI" %}

```bash
nexus keys create   # secret is shown ONCE — store it now
```

{% endtab %}
{% endtabs %}

**Request body**

```json
{
  "label": "my-bot"
}
```

**Response**

```json
{
  "key_id": "nx_7f3a1b...",
  "secret": "e4d2c8f1...long_hex..."
}
```

## 3. Sign requests

`GET /markets` — **HMAC API key required.**

Every authenticated request needs three headers. Build a canonical string, HMAC-SHA256 it with your secret, and attach the result.

**Required headers**

| Header        | Required | Description                             |
| ------------- | -------- | --------------------------------------- |
| `X-API-Key`   | yes      | Your key ID (`nx_...`)                  |
| `X-Timestamp` | yes      | Current time in ms since epoch          |
| `X-Signature` | yes      | HMAC-SHA256 hex of the canonical string |

**Notes**

* Canonical format: `timestamp\nMETHOD\npath\nquery\nsha256(body)`
* `path` is the path **as written in the contract** — include the `/api/v1` prefix when the route has one, but **not** the `/api/exchange` gateway mount, which is stripped before your signature is verified. Calling `…/api/exchange/markets` means signing `/markets`; calling `…/api/exchange/api/v1/tickers` means signing `/api/v1/tickers`.
* Timestamp must be within ±30 seconds of server time (milliseconds since epoch).
* For GET requests with no body, hash the empty string.

{% tabs %}
{% tab title="cURL" %}

```bash
# Build the HMAC signature
TIMESTAMP=$(python3 -c 'import time; print(int(time.time()*1000))')
BODY_HASH=$(echo -n "" | shasum -a 256 | cut -d' ' -f1)
CANONICAL="$TIMESTAMP\nGET\n/markets\n\n$BODY_HASH"
SIGNATURE=$(echo -ne "$CANONICAL" | \
  openssl dgst -sha256 -mac HMAC -macopt "hexkey:$NEXUS_API_SECRET" -hex | awk '{print $NF}')

curl 'https://exchange.nexus.xyz/api/exchange/markets' \
  -H "X-API-Key: nx_7f3a1b..." \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE"
```

{% endtab %}

{% tab title="Rust" %}

```rust
use nexus_exchange::{Client, Config, Network};

// The SDK builds the canonical string and HMAC-signs every request.
let client = Client::new(Config::new(Network::Stable).api_key(
    std::env::var("NEXUS_API_KEY")?,
    std::env::var("NEXUS_API_SECRET")?,
));

let markets = client.fetch_markets().await?;
println!("{} markets", markets.len());
```

{% endtab %}

{% tab title="Python" %}

```python
import os
from nexus_exchange import Client

# The SDK builds the canonical string and HMAC-signs every request.
client = Client(
    api_key=os.environ["NEXUS_API_KEY"],
    api_secret=os.environ["NEXUS_API_SECRET"],
)

print(len(client.fetch_markets()), "markets")
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
import { Client, Network } from "@nexus-xyz/exchange-ts";

// The SDK builds the canonical string and HMAC-signs every request.
const client = new Client({
  network: Network.Stable,
  apiKey: process.env.NEXUS_API_KEY,
  apiSecret: process.env.NEXUS_API_SECRET,
});

console.log((await client.fetchMarketSummaries()).length, "markets");
```

{% endtab %}

{% tab title="CLI" %}

```bash
nexus setup            # interactive; stores credentials (mode 0600)
# ...or per shell:
export NEXUS_API_KEY=nx_...
export NEXUS_API_SECRET=...
nexus balance          # every request is HMAC-signed for you
```

{% endtab %}
{% endtabs %}

**Response**

```json
[
  { "id": "BTC-USDX-PERP", "base": "BTC", "quote": "USDX", "status": "active" },
  { "id": "ETH-USDX-PERP", "base": "ETH", "quote": "USDX", "status": "active" }
]
```

{% hint style="info" %}
In the interactive docs this step has a live "Try it" button against `GET /markets`.
{% endhint %}

***

## Trading

Steps 4–7 fund the account and put a position on.

## 4. Fund account

`POST /account/credit` — **HMAC API key required.** Testnet surface.

Credit synthetic USDX to start trading. Each API key can claim up to 500 USDX per day — omit `"amount"` to claim the full remaining daily allowance.

{% hint style="warning" %}
The credit faucet is a **testnet** affordance. On the mainnet real-funds surface this endpoint returns `403` and funding is bridge-only — see the mainnet variant below.
{% endhint %}

**Notes**

* Amounts are decimal strings, like all monetary values in the API.
* Returns 429 once the daily allowance is used up; it resets the next UTC day.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST 'https://exchange.nexus.xyz/api/exchange/api/v1/account/credit' \
  -H 'X-API-Key: nx_7f3a1b...' \
  -H 'X-Timestamp: UNIX_MS' \
  -H 'X-Signature: HMAC_HEX' \
  -H 'Content-Type: application/json' \
  -d '{"amount": "500"}'
```

{% endtab %}

{% tab title="Rust" %}

```rust
use nexus_exchange::types::Decimal;

// `client` is the HMAC-credentialed client from step 3.
// Pass None to claim the full remaining daily allowance.
let credit = client
    .claim_credit(Some("500".parse::<Decimal>()?))
    .await?;
println!("credited {} (today: {})", credit.amount, credit.credited_today);
```

{% endtab %}

{% tab title="Python" %}

```python
# `client` is the HMAC-credentialed client from step 3.
credit = client.claim_credit("500")  # omit the amount for the daily max
print(credit.amount, credit.credited_today)
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
// `client` is the HMAC-credentialed client from step 3.
const credit = await client.claimCredit({ amount: "500" }); // {} = daily max
console.log(credit.amount, credit.credited_today);
```

{% endtab %}

{% tab title="CLI" %}

```bash
nexus account credit --amount 500   # omit --amount for the daily max
```

{% endtab %}
{% endtabs %}

**Request body**

```json
{
  "amount": "500"
}
```

**Response**

```json
{
  "amount": "500",
  "credited_today": "500",
  "daily_limit": "500"
}
```

### Mainnet surface variant — step 4: Fund via bridge

On the mainnet real-funds surface (mainnet: **2026-05-20**), step 4 is replaced by a bridge deposit. Funding differs fundamentally per surface: the testnet play surface has a synthetic-credit faucet; the mainnet real-funds surface will be bridge-only.

`POST /bridge/deposit-addresses` — **HMAC API key required.**

Real funds: there is no synthetic credit on mainnet. Get your per-account deposit address, bridge USDX from Ethereum Mainnet to it, and your exchange account is credited once the deposit confirms.

**Notes**

* `POST /account/credit` is testnet-only — it returns 403 on mainnet; the bridge is the sole funding path.
* Idempotent per (account, chain): repeated calls return the same address.
* `GET /bridge/assets` lists depositable assets per chain with minimum amounts, required confirmations, and fees — check it before sending.
* Track crediting with `GET /bridge/deposits` (or `/bridge/deposits/{id}`): status moves to `credited` once required confirmations are reached.
* On-chain transfers are irreversible — send only supported assets to this address, from a wallet you control.
* Round trip: fund here → trade (next steps) → withdrawals: `GET /withdrawals` lists your records; withdrawal initiation is not yet exposed through the public API.

{% tabs %}
{% tab title="cURL" %}

```bash
# 1) Get (or create) your deposit address on Ethereum Mainnet
curl -X POST 'https://exchange.nexus.xyz/api/exchange/api/v1/bridge/deposit-addresses' \
  -H 'X-API-Key: nx_7f3a1b...' \
  -H 'X-Timestamp: UNIX_MS' \
  -H 'X-Signature: HMAC_HEX' \
  -H 'Content-Type: application/json' \
  -d '{"chain": "ethereum"}'

# 2) Send USDX to the returned address (from your own wallet), then track it:
curl 'https://exchange.nexus.xyz/api/exchange/api/v1/bridge/deposits' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'
```

{% endtab %}

{% tab title="Rust" %}
Not available in Rust yet — use the cURL example. The white-glove client wrap for the bridge step is still in progress.
{% endtab %}

{% tab title="Python" %}
Not available in Python yet — use the cURL example.
{% endtab %}

{% tab title="TypeScript" %}
Not available in TypeScript yet — use the cURL example.
{% endtab %}

{% tab title="CLI" %}
Not available in the CLI yet — use the cURL example.
{% endtab %}
{% endtabs %}

**Request body**

```json
{
  "chain": "ethereum"
}
```

**Response**

```json
{
  "address": "0xDEPOSIT_ADDRESS",
  "chain": "ethereum",
  "accepts": ["USDC", "USDX"],
  "account_id": "0xYOUR_WALLET_ADDRESS",
  "created_at": 1779225381000
}
```

## 5. Browse markets

`GET /markets/{market_id}/ticker` — **HMAC API key required.**

List available perpetual futures markets and check current prices.

{% tabs %}
{% tab title="cURL" %}

```bash
# List markets (4 trading on testnet today; 32 configured)
curl 'https://exchange.nexus.xyz/api/exchange/markets' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'

# Get a single ticker
curl 'https://exchange.nexus.xyz/api/exchange/api/v1/markets/BTC-USDX-PERP/ticker' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'
```

{% endtab %}

{% tab title="Rust" %}

```rust
let markets = client.fetch_markets().await?;
println!("{} markets", markets.len());

let ticker = client.fetch_ticker("BTC-USDX-PERP").await?;
println!(
    "{}: last={:?} mark={:?}",
    ticker.symbol, ticker.last, ticker.mark_price
);
```

{% endtab %}

{% tab title="Python" %}

```python
for market in client.fetch_markets():
    print(market.market_id)

ticker = client.fetch_ticker("BTC-USDX-PERP")
print(ticker.last, ticker.mark_price)
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
for (const market of await client.fetchMarketSummaries()) {
  console.log(market.market_id);
}

const ticker = await client.fetchTicker("BTC-USDX-PERP");
console.log(ticker.last, ticker.markPrice);
```

{% endtab %}

{% tab title="CLI" %}

```bash
nexus markets                 # tradable markets and their rules
nexus ticker BTC-USDX-PERP    # ticker for one market
```

{% endtab %}
{% endtabs %}

**Response**

```json
{
  "symbol": "BTC-USDX-PERP",
  "last": 84250.5,
  "bid": 84249.0,
  "ask": 84252.0,
  "volume": 1523.4,
  "change": 2.1
}
```

{% hint style="info" %}
The source comment for this step reads `# List markets (all 32)`. That is the configured-market count, not the live one — the testnet is currently trading **4** markets, so the comment above has been corrected. See [Exchange Testnet](https://docs.nexus.xyz/exchange/exchange-testnet) for the current set.

On the mainnet surface the market-set copy differs: mainnet launches with 3 markets — `BTC-USDX-PERP`, `ETH-USDX-PERP`, `SOL-USDX-PERP` — expanding to 32+. The cURL comment there reads `# List markets (3 at internal launch: BTC, ETH, SOL — expanding to 32+)`.

In the interactive docs this step has a live "Try it" button against `GET /markets/BTC-USDX-PERP/ticker`.
{% endhint %}

## 6. Place an order

`POST /orders` — **HMAC API key required.**

Submit a limit or market order. The response confirms acceptance.

**Notes**

* Use `"type": "market"` to fill immediately at best available price.
* Batch multiple orders in a single `POST /orders/batch` call — processed sequentially, results preserve request order.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST 'https://exchange.nexus.xyz/api/exchange/api/v1/orders' \
  -H 'X-API-Key: nx_7f3a1b...' \
  -H 'X-Timestamp: UNIX_MS' \
  -H 'X-Signature: HMAC_HEX' \
  -H 'Content-Type: application/json' \
  -d '{
    "market_id": "BTC-USDX-PERP",
    "side": "buy",
    "type": "limit",
    "size": 0.01,
    "price": 83000.00
  }'
```

{% endtab %}

{% tab title="Rust" %}

```rust
use nexus_exchange::types::{OrderRequest, Side, TimeInForce};

let order = OrderRequest::limit(
    "BTC-USDX-PERP",
    Side::Buy,
    "83000".parse()?,
    "0.01".parse()?,
    TimeInForce::Gtc,
);
let placed = client.create_order(&order).await?;
println!("placed {} — {}", placed.order.id, placed.order.status);
```

{% endtab %}

{% tab title="Python" %}

```python
from decimal import Decimal
from nexus_exchange import OrderRequest

order = OrderRequest.limit(
    "BTC-USDX-PERP", "Buy", Decimal("83000"), Decimal("0.01")
)
placed = client.create_order(order)
print(placed.order.id, placed.order.status)
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
const { order } = await client.placeOrder({
  market_id: "BTC-USDX-PERP",
  side: "Buy",
  order_type: "Limit",
  price: "83000",
  quantity: "0.01",
  time_in_force: "GTC",
});
console.log(order.id, order.status);
```

{% endtab %}

{% tab title="CLI" %}

```bash
# Prompts for confirmation; pass --yes to skip
nexus order place --market BTC-USDX-PERP --side buy --type limit \
  --price 83000 --quantity 0.01 --tif GTC
```

{% endtab %}
{% endtabs %}

**Request body**

```json
{
  "market_id": "BTC-USDX-PERP",
  "side": "buy",
  "type": "limit",
  "size": 0.01,
  "price": 83000.0
}
```

**Response**

```json
{
  "id": "ord_f82a...",
  "status": "open",
  "filled": 0.0,
  "market_id": "BTC-USDX-PERP",
  "side": "buy",
  "type": "limit",
  "size": 0.01,
  "price": 83000.0
}
```

## 7. Monitor positions

`GET /positions` — **HMAC API key required.**

Check open positions, unrealized PnL, and account health.

{% tabs %}
{% tab title="cURL" %}

```bash
# Open positions
curl 'https://exchange.nexus.xyz/api/exchange/api/v1/positions' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'

# Account summary
curl 'https://exchange.nexus.xyz/api/exchange/api/v1/account' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'
```

{% endtab %}

{% tab title="Rust" %}

```rust
let account = client.fetch_balance().await?;
println!("equity {}", account.equity);

for p in client.fetch_positions().await? {
    println!(
        "{} {} size {} | uPnL {}",
        p.market_id, p.side, p.size, p.unrealized_pnl
    );
}
```

{% endtab %}

{% tab title="Python" %}

```python
account = client.fetch_balance()
print(account.equity)

for p in client.fetch_positions():
    print(p.market_id, p.side, p.size, p.unrealized_pnl)
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
const account = await client.getAccount();
console.log(account.equity);

for (const p of await client.getPositions()) {
  console.log(p.market_id, p.side, p.size, p.unrealized_pnl);
}
```

{% endtab %}

{% tab title="CLI" %}

```bash
nexus positions   # open positions with PnL
nexus balance     # balance, collateral, equity, margin
```

{% endtab %}
{% endtabs %}

**Response**

```json
{
  "balance": 10000.0,
  "equity": 10012.5,
  "margin_used": 83.0,
  "margin_ratio": 0.008,
  "positions": 1
}
```

{% hint style="info" %}
In the interactive docs this step has a live "Try it" button against `GET /account`.
{% endhint %}

***

## Clients

The snippets above use these packages:

| Client     | Package / crate          |
| ---------- | ------------------------ |
| Rust       | `nexus_exchange`         |
| Python     | `nexus_exchange`         |
| TypeScript | `@nexus-xyz/exchange-ts` |
| CLI        | the `nexus` command      |

The CLI and the language SDKs are distributed outside the Exchange monorepo. The guided walkthrough does not state their repositories, so install instructions are not reproduced here.

## Next steps

* [Overview](/api-reference/readme.md) — what the Exchange API covers and how it is organised
* [Authentication](/api-reference/guides/authentication.md) — session tokens, HMAC canonicalisation, and API-key management in full
* [Order Types](/api-reference/guides/order-types.md) — the requirement matrix for all eight order types, and the Trading pages in the Reference sidebar
* [`GET /stream`](/api-reference/websocket/connect-stream.md) and the WebSocket pages in the Reference sidebar — token minting, channels, message envelopes, and reconnection


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.nexus.xyz/api-reference/guides/get-started.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
