> 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/authentication.md).

# Autenticación

Inicio de sesión con billetera EVM y administración de claves de API, en cuatro operaciones.

Intervienen dos credenciales, y no son intercambiables:

1. **Token de sesión.** Lo obtienes firmando un mensaje fijo con tu billetera EVM (EIP-191 `personal_sign`). Es un token `Bearer`, dura **24 horas** y autentica **solo** los endpoints `/keys`. No puedes operar con él.
2. **Clave de API.** Un par `key_id` + `secret` generado con el token de sesión. Firmas cada solicitud de trading y de cuenta con el secreto, usando HMAC-SHA256. El secreto se devuelve **una sola vez** al crearla y nunca se guarda ni se vuelve a mostrar.

```
POST /auth/login   (wallet signature)         → session Bearer token
POST /keys         (Bearer)                    → key_id + secret
sign each request  (HMAC over canonical str)   → trade
```

Para una firma delegada que evita exponer tu billetera principal, consulta [Agentes](/api-reference/es-419/guides/agent-keys.md).

URL base de todos los ejemplos de abajo: `https://api.testnet.nexus.xyz/v1`, la base pública de testnet.

***

## `POST /auth/login`

Iniciar sesión con billetera EVM.

Envía una firma EIP-191 `personal_sign` para recibir un token de sesión. Usa el token de sesión para crear y administrar claves de API a través de los endpoints `/keys`. Para operar, usa en cambio claves de API HMAC. Los tokens de sesión vencen a las 24 horas.

**Autenticación:** ninguna. La solicitud se autentica a sí misma con la firma de billetera que lleva.

### Cuerpo de la solicitud

`LoginRequest`, `application/json`, obligatorio.

| Campo       | Tipo   | Obligatorio | Descripción                                               |
| ----------- | ------ | ----------- | --------------------------------------------------------- |
| `message`   | string | Sí          | Debe ser exactamente: `Sign in to Nexus Exchange`         |
| `signature` | string | Sí          | Hex de EIP-191 `personal_sign` (con prefijo 0x, 65 bytes) |

El mensaje es una cadena fija, no un desafío con nonce, y no hay una llamada aparte para "solicitar un desafío". El servidor *recupera* la dirección de tu billetera a partir de la firma, así que no la envías.

### Respuestas

#### `200`

Sesión creada. `LoginResponse`.

| Campo     | Tipo   | Descripción                                                                                   |
| --------- | ------ | --------------------------------------------------------------------------------------------- |
| `token`   | string | Token de sesión (hex de 64 caracteres). Úsalo como token `Bearer` para los endpoints `/keys`. |
| `address` | string | Dirección de Ethereum recuperada (con prefijo 0x)                                             |

#### `401`

Falló la verificación de la firma.

### Ejemplo

```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": "0x1234...abcd"
  }'
```

Respuesta:

```json
{
  "token": "a1b2c3d4e5f6...",
  "address": "0xAbCdEf0123456789..."
}
```

***

## `POST /keys`

Crear una clave de API.

Crea una nueva clave de API HMAC para la billetera autenticada. Devuelve el secreto una sola vez. Nunca se guarda ni se vuelve a mostrar. Requiere un token de sesión (Bearer) de `POST /auth/login`.

**Autenticación:** `bearerAuth` (token de sesión).

### Cuerpo de la solicitud

Opcional. [`CreateKeyRequest`](https://docs.nexus.xyz/api-reference/guides/schemas#createkeyrequest). Un cuerpo ausente o vacío equivale a `{}`.

| Campo    | Tipo    | Descripción                                                                                                                                                                           |
| -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`  | string  | Etiqueta que asigna quien llama a esta clave, y que se devuelve en `GET /keys`.                                                                                                       |
| `ttl_ms` | integer | Cuánto debe durar la clave, en milisegundos desde su creación. Omítelo para una clave que nunca vence. Debe estar en `[24h, 90d]` (86400000–7776000000 ms) o la solicitud se rechaza. |

### Respuestas

#### `200`

Clave creada. [`CreateKeyResponse`](https://docs.nexus.xyz/api-reference/guides/schemas#createkeyresponse).

| Campo           | Tipo           | Descripción                                                                                                                                                                                                                                                                                                                                                       |
| --------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key_id`        | string         | El identificador de la clave. Envíalo como `X-API-Key` en las solicitudes firmadas.                                                                                                                                                                                                                                                                               |
| `secret`        | string         | El secreto HMAC, en hex. **Se devuelve una sola vez.** Guárdalo de inmediato. No hay forma de recuperarlo.                                                                                                                                                                                                                                                        |
| `expires_at_ms` | integer o null | Ms Unix a partir de los cuales esta clave deja de autenticar, o `null` si nunca vence. Es el valor resuelto de `ttl_ms`. **Admite null, pero no es opcional:** siempre está presente. Hoy solo lo aplican los despliegues respaldados por Postgres. Una clave creada en un despliegue sin Postgres acepta un `ttl_ms`, pero todavía no rechaza una clave vencida. |

#### `400`

Solicitud incorrecta:

| `code`             | Significado                                                                                                                                               |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ttl_ms_invalid`   | `ttl_ms` está presente pero no es un entero no negativo, o no se pudo leer el cuerpo de la solicitud en sí (supera el límite de 8KB o no es JSON válido). |
| `ttl_out_of_range` | Un `ttl_ms` bien formado queda fuera de `[24h, 90d]`.                                                                                                     |

#### `401`

Se requiere un token de sesión válido.

### Ejemplo

```bash
curl -X POST 'https://api.testnet.nexus.xyz/v1/keys' \
  -H 'Authorization: Bearer a1b2c3d4e5f6...' \
  -H 'Content-Type: application/json' \
  -d '{"label": "my trading bot", "ttl_ms": 2592000000}'
```

Respuesta:

```json
{
  "key_id": "nx_a1b2c3d4e5f67890",
  "secret": "deadbeef...",
  "expires_at_ms": 1735689600000
}
```

Las claves nuevas reciben el nivel **Pro** de forma predeterminada. Un operador asigna los niveles con [`PUT /admin/tiers`](https://docs.nexus.xyz/api-reference/admin/set-tier), y cada respuesta informa los topes por nivel en los encabezados `X-RateLimit-*`.

***

## `GET /keys`

Listar tus claves de API.

Devuelve los ID y los niveles de todas las claves que pertenecen a la billetera autenticada. No incluye los secretos.

**Autenticación:** `bearerAuth` (token de sesión).

### Respuestas

#### `200`

Las claves de API de la sesión. Un arreglo simple. El contrato da un ejemplo, pero ningún esquema con nombre.

| Campo    | Tipo   | Descripción                                                                         |
| -------- | ------ | ----------------------------------------------------------------------------------- |
| `key_id` | string | El identificador de la clave                                                        |
| `tier`   | string | Nivel de límites de solicitudes asignado a esta clave, p. ej. `Pro`, `Market Maker` |

#### `401`

Se requiere un token de sesión válido.

### Ejemplo

```bash
curl 'https://api.testnet.nexus.xyz/v1/keys' \
  -H 'Authorization: Bearer a1b2c3d4e5f6...'
```

Respuesta:

```json
[
  {
    "key_id": "nx_a1b2c3d4e5f67890",
    "tier": "Pro"
  }
]
```

***

## `DELETE /keys/{key_id}`

Eliminar una clave de API.

Elimina una clave que te pertenece. No se pueden eliminar claves que pertenecen a otras billeteras.

**Autenticación:** `bearerAuth` (token de sesión).

### Parámetros

| Nombre   | En   | Tipo   | Obligatorio | Descripción                                   |
| -------- | ---- | ------ | ----------- | --------------------------------------------- |
| `key_id` | path | string | Sí          | El identificador de la clave que se eliminará |

### Respuestas

#### `200`

Clave eliminada.

#### `401`

Se requiere un token de sesión válido.

#### `404`

Clave no encontrada o que no te pertenece. Las fallas de propiedad devuelven `404`, no `403`, para que no puedas sondear los ID de claves de otras billeteras.

### Ejemplo

```bash
curl -X DELETE 'https://api.testnet.nexus.xyz/v1/keys/nx_a1b2c3d4e5f67890' \
  -H 'Authorization: Bearer a1b2c3d4e5f6...'
```

***

## Cómo firmar una solicitud con la clave

Una vez que tienes un `key_id` y un `secret`, cada operación `hmacAuth` necesita tres encabezados:

| Encabezado    | Valor                                        |
| ------------- | -------------------------------------------- |
| `X-API-Key`   | Tu ID de clave, p. ej. `nx_a1b2c3d4e5f67890` |
| `X-Timestamp` | Hora actual en **milisegundos** Unix         |
| `X-Signature` | `hex(hmac_sha256(secret, canonical))`        |

La cadena canónica tiene cinco campos separados por saltos de línea:

```
<timestamp>\n<METHOD>\n<path>\n<query>\n<sha256_hex(body)>
```

* `path` es la ruta **tal como está escrita en el contrato**, *no* la ruta completa de la URL que llamaste. El prefijo de transporte `/v1` se elimina antes de que la solicitud llegue al servicio que verifica tu firma, así que **no** debe firmarse. Sí incluye el prefijo `/api/v1` cuando llames a una ruta versionada, porque esa parte se reenvía.

  | Llamas a                                       | Firmas            |
  | ---------------------------------------------- | ----------------- |
  | `https://api.testnet.nexus.xyz/v1/markets`     | `/markets`        |
  | `https://api.testnet.nexus.xyz/api/v1/tickers` | `/api/v1/tickers` |

  Firmar el prefijo de transporte `/v1` es la segunda causa más común de un `401` opaco, después del desfase del reloj.
* `query` es la cadena de consulta sin procesar, vacía si no hay ninguna.
* Para las solicitudes sin cuerpo, calcula el hash de la cadena vacía.
* La marca de tiempo debe estar dentro de **30 segundos** respecto a la hora del servidor. Un reloj desfasado es la causa más común de un `401` opaco.

Los encabezados informativos `X-Nexus-Api-Version` y `User-Agent` están **excluidos** de la cadena canónica.

```bash
TIMESTAMP=$(python3 -c 'import time; print(int(time.time()*1000))')
BODY_HASH=$(printf '' | shasum -a 256 | cut -d' ' -f1)
CANONICAL="$TIMESTAMP\nGET\n/markets\n\n$BODY_HASH"
SIGNATURE=$(printf '%s' "$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_a1b2c3d4e5f67890" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE"
```

Todas las respuestas `401` devuelven el mismo cuerpo opaco, `{"code":"unauthorized"}`, así que la respuesta no te dice si el problema fue la clave, la firma o el reloj. Revisa primero el desfase del reloj, luego la cadena canónica y después la clave.

> **Estado:** versión preliminar de testnet. Las credenciales, las sesiones y el estado de los límites de solicitudes todavía no sobreviven a los reinicios del gateway, así que trata las claves de API como recreables.


---

# 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/authentication.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.
