> 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/es-419/guides/get-started.md).

# Primeros pasos

Un recorrido de ocho pasos desde cero hasta una posición abierta en Nexus Exchange. Inicias sesión con tu billetera, generas una clave de API HMAC, firmas solicitudes, fondeas la cuenta, exploras los mercados, envías una orden, la cancelas o la modificas y monitoreas tus posiciones.

Cada paso se muestra en cinco clientes: cURL, Rust, Python, TypeScript y la CLI del Exchange. Elige una pestaña en cada paso.

Esta página nació como la pestaña **Getting Started** de la documentación interactiva de la API que la app del Exchange servía en `/api-docs`. Esa ruta ya no resuelve, así que ahora esta página es la guía.

## Antes de empezar

* **Necesitas una billetera de Ethereum** para firmar el mensaje de inicio de sesión. No se requiere nada más para empezar.
* **URL base.** Los ejemplos de abajo usan el host público de testnet. Las rutas sin prefijo van bajo la base de transporte `/v1`, `https://api.testnet.nexus.xyz/v1`, y las rutas `/api/v1` van en la raíz del host, así que una URL completa se ve como `https://api.testnet.nexus.xyz/api/v1/…`. Si lo ejecutas localmente, la base es `http://localhost:9090`. Sustituye la base por la del despliegue al que llamas. Las rutas se muestran con el prefijo `/api/v1` donde existe una ruta versionada. La forma sin prefijo sobre la base `/v1` llega a la misma operación y es hacia la que se están moviendo los clientes oficiales. Consulta [URL base](/api-reference/es-419/readme.md#base-urls) para ver las otras bases que declara el contrato y cómo se resuelve la anulación de `servers` en las rutas `/api/v1`.
* **Autenticación.** Dos esquemas: un **token de sesión** (Bearer) que se usa solo para crear y administrar claves de API, y la firma con clave de API **HMAC-SHA256** que se usa para todo lo demás, incluido todo el trading.
* **Dos despliegues.** La app del Exchange se despliega dos veces a partir de un mismo código. El despliegue de **testnet** está en vivo y fondea las cuentas desde un faucet de crédito sintético. El despliegue de **mainnet** con fondos reales se fondeará transfiriendo USDX por el puente desde Ethereum Mainnet. Todavía no está en vivo: su host, `api.nexus.xyz`, no resuelve. El paso 4 de abajo difiere entre los dos, y ambas variantes están documentadas.
* **Marcadores de posición.** Valores como `0xSIGNATURE_HEX`, `nx_7f3a1b...`, `sess_abc123...` y `0x<wallet-private-key>` son marcadores de posición. Sustitúyelos por los tuyos; nunca hagas commit de un secreto.

### Cobertura de lenguajes

cURL es la base, y cada paso tiene un ejemplo en cURL. Los cuatro clientes SDK/CLI todavía no cubren todos los pasos. Cuando un cliente no tiene ejemplo para un paso, la pestaña lo indica, y sigues el ejemplo de cURL en su lugar. La documentación interactiva hacía lo mismo: recurría a cURL con una nota.

### Puntos de entrada legibles por máquina

Un agente puede empezar por estos sin leer esta página:

* `llms.txt`, en <https://exchange.nexus.xyz/llms.txt>
* `openapi.json`, el contrato OpenAPI, en `https://api.testnet.nexus.xyz/openapi.json`
* `/metadata`, la ruta de metadatos legible por máquina de la app del Exchange
* El **servidor MCP**, publicado en npm, así que agregarlo es una sola línea. Se ejecuta localmente por stdio, así que tu clave de API se queda en tu máquina:

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

Sus herramientas públicas de datos de mercado y de demostración no necesitan credenciales, así que el comando es útil antes de que tengas una clave. Está planificado un endpoint MCP alojado; su DNS todavía no está activo, así que hoy no hay una URL remota que agregar.

La especificación OpenAPI y el changelog se versionan en [nexus-xyz/nexus-exchange-api](https://github.com/nexus-xyz/nexus-exchange-api), y las versiones se publican en [GitHub Releases](https://github.com/nexus-xyz/nexus-exchange-api/releases).

***

## Autenticación

Los pasos 1–3 te llevan de una billetera a una solicitud firmada.

## 1. Inicia sesión

`POST /auth/login`. No requiere autenticación.

Autentícate con una firma personal EIP-191. El mensaje que se firma siempre es la cadena fija "Sign in to Nexus Exchange". El servidor recupera la dirección de tu billetera a partir de la firma.

**Notas**

* El token de sesión vence en 24 horas.
* Solo necesitas la sesión para crear y administrar claves de API, no para operar.

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

```bash
curl -X POST 'https://api.testnet.nexus.xyz/v1/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::Testnet));

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" %}
Todavía no está disponible en TypeScript. Usa el ejemplo de cURL.
{% 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 %}

**Cuerpo de la solicitud**

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

**Respuesta**

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

## 2. Crea una clave de API

`POST /keys`. **Requiere token de sesión.**

Usa el token de sesión para crear un par de claves HMAC. El secreto se muestra una sola vez, así que guárdalo de inmediato.

**Notas**

* No puedes recuperar el secreto después de esta respuesta.
* Las claves heredan el nivel de tu cuenta. Los encabezados de respuesta `X-RateLimit-*` informan los límites de solicitudes por nivel.

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

```bash
curl -X POST 'https://api.testnet.nexus.xyz/v1/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::Testnet).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" %}
Todavía no está disponible en Python. Usa el ejemplo de cURL.
{% endtab %}

{% tab title="TypeScript" %}
Todavía no está disponible en TypeScript. Usa el ejemplo de cURL.
{% endtab %}

{% tab title="CLI" %}

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

{% endtab %}
{% endtabs %}

**Cuerpo de la solicitud**

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

**Respuesta**

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

## 3. Firma las solicitudes

`GET /markets`. **Requiere clave de API HMAC.**

Cada solicitud autenticada necesita tres encabezados. Construye una cadena canónica, aplícale HMAC-SHA256 con tu secreto y adjunta el resultado.

**Encabezados obligatorios**

| Encabezado    | Obligatorio | Descripción                              |
| ------------- | ----------- | ---------------------------------------- |
| `X-API-Key`   | sí          | Tu ID de clave (`nx_...`)                |
| `X-Timestamp` | sí          | Hora actual en ms desde epoch            |
| `X-Signature` | sí          | HMAC-SHA256 en hex de la cadena canónica |

**Notas**

* Formato canónico: `timestamp\nMETHOD\npath\nquery\nsha256(body)`
* `path` es la ruta **tal como está escrita en el contrato**. Incluye el prefijo `/api/v1` cuando la ruta lo tiene, pero **no** el prefijo de transporte `/v1`, que se elimina antes de verificar tu firma. Llamar a `…/v1/markets` significa firmar `/markets`; llamar a `…/api/v1/tickers` significa firmar `/api/v1/tickers`.
* La marca de tiempo debe estar dentro de ±30 segundos respecto a la hora del servidor (milisegundos desde epoch).
* Para las solicitudes GET sin cuerpo, calcula el hash de la cadena vacía.

{% 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://api.testnet.nexus.xyz/v1/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::Testnet).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.Testnet,
  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 %}

**Respuesta**

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

{% hint style="info" %}
En la documentación interactiva, este paso tiene un botón "Try it" en vivo contra `GET /markets`.
{% endhint %}

***

## Trading

Los pasos 4–8 fondean la cuenta, abren una posición y la monitorean.

## 4. Fondea la cuenta

`POST /account/credit`. **Requiere clave de API HMAC.** Solo en testnet.

Acredita USDX sintético para empezar a operar. Cada clave de API puede reclamar hasta 500 USDX por día. Omite `"amount"` para reclamar todo lo que queda de la asignación diaria.

{% hint style="warning" %}
El faucet de crédito solo existe en **testnet**. En el despliegue de mainnet con fondos reales, este endpoint devuelve `403` y el fondeo es solo por el puente. Consulta la variante de mainnet más abajo.
{% endhint %}

**Notas**

* Los montos son cadenas decimales, como todos los valores monetarios de la API.
* Devuelve 429 cuando se agota la asignación diaria. La asignación se reinicia el siguiente día UTC.

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

```bash
curl -X POST 'https://api.testnet.nexus.xyz/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 %}

**Cuerpo de la solicitud**

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

**Respuesta**

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

### El paso 4 en mainnet: fondea con colateral real

En el despliegue de mainnet con fondos reales (planificado, todavía no en vivo), un depósito real reemplaza al paso 4. El despliegue de prueba de testnet tiene un faucet de crédito sintético, y el despliegue de mainnet con fondos reales no tiene ninguno. No tienes que ramificar tu código por eso. Un solo endpoint responde "cómo acepta colateral este despliegue", y la respuesta indica el modo.

[`GET /account/deposit-target`](https://docs.nexus.xyz/api-reference/account/fetch-deposit-address). **Requiere clave de API HMAC.**

No hay crédito sintético en mainnet. Pregúntale a la plataforma adónde enviar el colateral, envíalo y luego consulta periódicamente hasta que tu saldo lo refleje.

**No fijes en el código el método de fondeo.** La respuesta es una unión discriminada por `mode`. El modo que recibes es una propiedad del despliegue, no de tu solicitud, y ningún parámetro lo selecciona. Un despliegue con un contrato de depósito real configurado responde `onchain`. Todos los demás despliegues responden `testnet-faucet` y apuntan a sus endpoints de crédito sintético. Ramifica según `mode`, y el mismo código de cliente se fondea solo en cualquiera de los dos despliegues.

**Notas**

* Solo descubrimiento. `GET /account/deposit-target` no mueve fondos ni crea ningún depósito. Actuar según la instrucción devuelta es un paso aparte y explícito.
* En modo `onchain`, `onchain.address` es la dirección del contrato de depósito y `onchain.chain` es la cadena en la que vive. Ambos son configuración del despliegue, así que léelos y no los fijes en el código.
* **`403 EARLY_ACCESS_REQUIRED` significa que tu cuenta todavía no se puede fondear aquí.** Cuando un despliegue restringe el fondeo a participantes con acceso anticipado, rechaza una cuenta que no está inscrita, y el rechazo es **permanente hasta que la cuenta se inscriba. No reintentes.** La validación replica `POST /account/credit` y `POST /faucet` a propósito, para que a una cuenta que no se puede fondear no se le diga cómo fondearse.
* El endpoint nunca inventa una dirección para completar la forma `onchain`. Un despliegue configurado para depósitos on-chain cuya dirección está mal formada devuelve `503 DEPOSIT_TARGET_MISCONFIGURED` en lugar de publicarla, porque depositar en una dirección incorrecta quema los fondos. Es un error de configuración del operador, no una falla transitoria, y reintentar no lo resuelve.
* `min_amount` es **orientativo, no obligatorio**. Es el piso que hace viable una primera operación; nada rechaza un depósito on-chain más pequeño.
* `confirm` es idéntico en ambos modos, así que funciona en cualquiera de los dos despliegues. Consulta `GET /account` hasta que `balance` refleje los fondos antes de operar.
* `POST /account/credit` es un faucet **solo de testnet**, y el USDX acreditado es sintético. La orientación del propio contrato es no construir un flujo de fondeo que suponga que la operación existe en todas las redes. Mainnet no tiene ningún crédito sintético.
* [`GET /api/v1/bridge/assets`](https://docs.nexus.xyz/api-reference/bridge/fetch-bridge-assets) enumera las cadenas admitidas y, por cadena, los activos que se pueden depositar con sus decimales, su monto mínimo y las confirmaciones requeridas.
* Sigue un depósito entre cadenas con [`GET /api/v1/bridge/deposits`](https://docs.nexus.xyz/api-reference/bridge/fetch-bridge-deposits), o uno solo por su id `{tx_hash}:{log_index}` con [`GET /api/v1/bridge/deposits/{id}`](https://docs.nexus.xyz/api-reference/bridge/fetch-bridge-deposit). El watcher escribe ese modelo de lectura, y los endpoints solo lo leen.
* Las transferencias on-chain son irreversibles. Envía solo el activo que nombra la instrucción, desde una billetera que controles.
* El ciclo completo es: fondear aquí, operar (pasos siguientes) y luego retirar. `GET /withdrawals` enumera tus registros y [`POST /withdrawals`](https://docs.nexus.xyz/api-reference/account/withdraw) inicia uno. Se autentica con un `WithdrawIntent` EIP-712 firmado con la clave propia de la billetera, **no** con una clave de API, así que no reutiliza las credenciales HMAC de arriba. Un retiro por el puente es una operación aparte, [`POST /api/v1/bridge/withdrawals`](https://docs.nexus.xyz/api-reference/bridge/create-bridge-withdrawal).

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

```bash
# 1) Ask the venue how this deployment accepts collateral.
#    Branch on .mode — "onchain" or "testnet-faucet". Do not assume either shape.
curl 'https://api.testnet.nexus.xyz/v1/account/deposit-target' \
  -H 'X-API-Key: nx_7f3a1b...' \
  -H 'X-Timestamp: UNIX_MS' \
  -H 'X-Signature: HMAC_HEX'

# onchain mode answers with the deposit contract to send to:
#   { "mode": "onchain", "account": "0x742d...", "asset": "USDX", "min_amount": "10",
#     "onchain": { "chain": "nexus-mainnet", "asset": "USDX",
#                  "address": "0x1f98...", "min_amount": "10" },
#     "confirm": { "method": "GET", "path": "/account", "poll_field": "balance" } }

# 2) Send the named asset to onchain.address on onchain.chain from your own wallet.

# 3) Confirm with the instruction's own confirm block — poll until balance moves.
curl 'https://api.testnet.nexus.xyz/v1/account' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'

# Optional: the cross-chain deposit record, once the watcher has seen it.
curl 'https://api.testnet.nexus.xyz/api/v1/bridge/deposits' \
  -H 'X-API-Key: ...' -H 'X-Timestamp: ...' -H 'X-Signature: ...'
```

{% endtab %}

{% tab title="Rust" %}
Todavía no está disponible en Rust. Usa el ejemplo de cURL. El wrapper de cliente de alto nivel para el paso del puente todavía está en desarrollo.
{% endtab %}

{% tab title="Python" %}
Todavía no está disponible en Python. Usa el ejemplo de cURL.
{% endtab %}

{% tab title="TypeScript" %}
Todavía no está disponible en TypeScript. Usa el ejemplo de cURL.
{% endtab %}

{% tab title="CLI" %}
Todavía no está disponible en la CLI. Usa el ejemplo de cURL.
{% endtab %}
{% endtabs %}

**Cuerpo de la solicitud**

Ninguno. `GET /account/deposit-target` no acepta parámetros ni cuerpo.

**Respuesta** (modo `onchain`, el ejemplo del contrato para `DepositTarget`)

```json
{
  "mode": "onchain",
  "account": "0x742d35cc6634c0532925a3b844bc9e7595f0beb0",
  "asset": "USDX",
  "min_amount": "10",
  "onchain": {
    "chain": "nexus-mainnet",
    "asset": "USDX",
    "address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
    "token_address": "0xf92b58d2225a73b45ded3bc2290ac1a2077c1cf2",
    "min_amount": "10",
    "instructions": "Approve USDX spend for the deposit contract, then call depositTo(token, amount, beneficiary) with token set to `onchain.token_address`, amount in USDX base units, and beneficiary set to `account`. Only USDX is accepted; other tokens are rejected on-chain. Funds credit to the exchange account within 30s of on-chain confirmation."
  },
  "confirm": {
    "method": "GET",
    "path": "/account",
    "poll_field": "balance",
    "note": "Poll until balance reflects the deposit (SPEC target: within 30s of on-chain confirmation)."
  }
}
```

## 5. Explora los mercados

`GET /markets/{market_id}/ticker`. **Requiere clave de API HMAC.**

Enumera los mercados de futuros perpetuos disponibles y consulta los precios actuales.

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

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

# Get a single ticker
curl 'https://api.testnet.nexus.xyz/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 %}

**Respuesta**

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

{% hint style="info" %}
El comentario del código fuente de este paso dice `# List markets (all 32)`. Ese es el conteo de mercados configurados, no el de los que están en vivo. Actualmente la testnet opera **4** mercados, así que el comentario de arriba se corrigió. Consulta [Testnet del Exchange](https://docs.nexus.xyz/exchange/exchange-testnet) para ver el conjunto actual.

En el despliegue de mainnet, el conjunto de mercados es distinto. Mainnet se lanza con 3 mercados (`BTC-USDX-PERP`, `ETH-USDX-PERP`, `SOL-USDX-PERP`) y se ampliará a 32 o más. El comentario de cURL allí dice `# List markets (3 at internal launch: BTC, ETH, SOL — expanding to 32+)`.

En la documentación interactiva, este paso tiene un botón "Try it" en vivo contra `GET /markets/BTC-USDX-PERP/ticker`.
{% endhint %}

### Precisión de precio y tamaño

Redondea antes de enviar. Cada mercado declara tres reglas de cuantización, y la plataforma rechaza una orden que no las cumple en lugar de redondearla por ti.

| Campo en `GET /markets` | Regla                                                            |
| ----------------------- | ---------------------------------------------------------------- |
| `tick_size`             | El precio límite debe ser un múltiplo exacto de este valor.      |
| `lot_size`              | El tamaño de la orden debe ser un múltiplo exacto de este valor. |
| `min_order_size`        | El tamaño de la orden debe ser al menos este valor.              |

Para `BTC-USDX-PERP` son `0.5`, `0.001` y `0.001`. Así que un precio de `83000.25` no es válido, porque no es múltiplo de `0.5`, y tampoco lo es un tamaño de `0.0005`, que está por debajo tanto del lote como del mínimo. `83000.00` y `0.001` son válidos.

Lee los valores de cada mercado en lugar de fijarlos en el código. Difieren según el mercado (`ETH-USDX-PERP` es `0.10` y `0.01`, `SOL-USDX-PERP` es `0.01` y `0.1`), y son configuración que se define al listar el mercado. [Especificaciones de mercado (en inglés)](https://docs.nexus.xyz/exchange/trading/perpetuals/market-specifications) publica la tabla actual de cada mercado listado.

**Redondea hacia el lado seguro.** Redondea un precio de compra *hacia abajo* y un precio de venta *hacia arriba* al tick, y redondea los tamaños hacia abajo a la cuadrícula del lote. Redondear un tamaño hacia arriba puede hacer que la orden supere el margen que respalda tu patrimonio, y entonces la orden se rechaza por otro motivo.

## 6. Envía una orden

`POST /orders`. **Requiere clave de API HMAC.**

Envía una orden límite o de mercado. La respuesta confirma la aceptación.

**Notas**

* Usa `"type": "market"` para ejecutar de inmediato al mejor precio disponible.
* Agrupa varias órdenes en una sola llamada a `POST /orders/batch`. La plataforma las procesa en secuencia, y los resultados conservan el orden de la solicitud.

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

```bash
curl -X POST 'https://api.testnet.nexus.xyz/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 %}

**Cuerpo de la solicitud**

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

**Respuesta**

```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. Cancela o modifica

`DELETE /orders/{order_id}` · `DELETE /orders` · `PATCH /orders/{order_id}`. **Requiere clave de API HMAC.**

Son tres operaciones separadas:

| Operación                   | Efecto                                                                                      |
| --------------------------- | ------------------------------------------------------------------------------------------- |
| `DELETE /orders/{order_id}` | Cancela una orden en el libro.                                                              |
| `DELETE /orders`            | Cancela todas las órdenes en el libro, o todas las órdenes de un mercado con `?market_id=`. |
| `PATCH /orders/{order_id}`  | **Cancelar y reemplazar atómico**: cambia el precio y/o el tamaño en una sola llamada.      |

**Notas**

* **Una modificación devuelve un reemplazo con un id nuevo.** El cuerpo `200` es la orden nueva; el id que modificaste ya no existe. Sigue el id que recibes, no el que enviaste.
* En una modificación hay que enviar al menos uno de `price` o `size`.
* La verificación de margen previa a la operación de una modificación **excluye la reserva que todavía mantiene la orden que se reemplaza**, así que se dimensiona según el margen que agrega el reemplazo. Cambiar el precio con el mismo tamaño no necesita margen adicional, y reducir el tamaño libera margen en lugar de requerir más.
* Las órdenes de liquidación no se pueden modificar.
* Un `409` en una modificación significa que la orden cambió después de que la leíste. Se ejecutó o se canceló entre tu lectura y tu escritura.
* **Las cancelaciones consumen un presupuesto de límites de solicitudes separado del de los envíos.** Agotar tu presupuesto de órdenes nunca bloquea una cancelación. Un `429` con `bucket: cancel` es el único rechazo que significa que tu propio canal de cancelaciones está saturado. Consulta [Límites de solicitudes](/api-reference/es-419/guides/rate-limits.md).

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

```bash
# Amend a resting order's price — note the response carries a NEW order id
curl -X PATCH 'https://api.testnet.nexus.xyz/api/v1/orders/ORDER_ID?market_id=BTC-USDX-PERP' \
  -H 'X-API-Key: nx_7f3a1b...' \
  -H 'X-Timestamp: UNIX_MS' \
  -H 'X-Signature: HMAC_HEX' \
  -H 'Content-Type: application/json' \
  -d '{"price": 82500.00}'

# Cancel everything on one market
curl -X DELETE 'https://api.testnet.nexus.xyz/api/v1/orders?market_id=BTC-USDX-PERP' \
  -H 'X-API-Key: nx_7f3a1b...' -H 'X-Timestamp: UNIX_MS' -H 'X-Signature: HMAC_HEX'
```

{% endtab %}
{% endtabs %}

## 8. Monitorea tus posiciones

`GET /positions`. **Requiere clave de API HMAC.**

Consulta las posiciones abiertas, el PnL no realizado y la salud de la cuenta.

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

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

# Account summary
curl 'https://api.testnet.nexus.xyz/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 %}

**Respuesta**

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

{% hint style="info" %}
En la documentación interactiva, este paso tiene un botón "Try it" en vivo contra `GET /account`.
{% endhint %}

***

## WebSockets

Hacer polling está bien para empezar. Un libro en vivo o un feed de ejecuciones deberían usar el stream.

Hay dos sockets, y no son intercambiables:

* [`GET /stream`](https://docs.nexus.xyz/api-reference/websocket/connect-stream) es de datos de mercado públicos y **no necesita token**. Envía un solo mensaje `{"subscribe": [...]}`. Los frames del libro son instantáneas completas del top 20, así que no hay nada que reproducir después de una reconexión.
* [`GET /ws`](https://docs.nexus.xyz/api-reference/websocket/connect-web-socket) necesita un token de [`POST /ws/token`](https://docs.nexus.xyz/api-reference/websocket/create-ws-token) y lleva los canales por cuenta además de los públicos, con sobres `op`, números de secuencia y un cursor de reconexión.

Cada página tiene la lista de canales, las formas de los mensajes y las reglas de reconexión.

Antes de construir sobre ellos:

* **La cancelación al desconectar es opcional, por cuenta, y está desactivada de forma predeterminada.** Actívala con `PUT /account/cancel-on-disconnect` y léela con el `GET`. Es un interruptor de hombre muerto. Cuando tu última conexión autenticada se cae y no se reconecta dentro de la ventana de gracia, la plataforma cancela tus órdenes en el libro. Sin ella, una conexión caída deja tus órdenes activas.
* **Revisa `active`, no solo `enabled`.** `enabled` es tu propia activación. `active` también requiere el interruptor de la función del lado del exchange, así que `active` te dice si la cancelación al desconectar se va a activar. Una cuenta puede leer `enabled: true` y aun así no estar protegida.
* **El stream no es la fuente de verdad del estado de las posiciones.** Concilia contra `GET /positions` y `GET /account` después de cualquier reconexión en lugar de reproducir desde donde te quedaste.

## Clientes

Los fragmentos de arriba usan estos paquetes:

| Cliente    | Paquete / crate          |
| ---------- | ------------------------ |
| Rust       | `nexus_exchange`         |
| Python     | `nexus_exchange`         |
| TypeScript | `@nexus-xyz/exchange-ts` |
| CLI        | el comando `nexus`       |

La CLI y los SDK de lenguajes se distribuyen fuera del monorepo del Exchange. El recorrido guiado no indica sus repositorios, así que las instrucciones de instalación no se reproducen aquí.

## Próximos pasos

* [Descripción general](/api-reference/es-419/readme.md): qué cubre la API del Exchange y cómo está organizada
* [Autenticación](/api-reference/es-419/guides/authentication.md): tokens de sesión, canonicalización HMAC y administración de claves de API en detalle
* [Tipos de órdenes](/api-reference/es-419/guides/order-types.md): la matriz de requisitos de los ocho tipos de órdenes, y las páginas de Trading de la barra lateral de la Referencia
* [`GET /stream`](https://docs.nexus.xyz/api-reference/websocket/connect-stream) (público, sin token) y [`GET /ws`](https://docs.nexus.xyz/api-reference/websocket/connect-web-socket) (token de `POST /ws/token`): canales, formas de los mensajes y reconexión


---

# 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/es-419/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.
