# Autenticación

URL: https://docs.fxapis.com/es/authentication

> Claves, claves de administrador, entornos, alcances y rotación.



Cada solicitud bajo `/v1` necesita una API key o, desde la consola de fxapis, la
sesión de un miembro que inició sesión. `/healthz` y `/readyz` no necesitan ninguna.

```
Authorization: Bearer fx_live_7f3a9c21_ZmQ4YmE2MjNhOTg3ZmUxMGJjNGQ...
```

También se acepta la clave sola, sin `Bearer `, porque la gente pega ambas.

## La forma de una clave [#the-shape-of-a-key]

```
fx_live_7f3a9c21_ZmQ4YmE2MjNhOTg3ZmUxMGJjNGQ...
── ──── ──────── ──────────────────────────────
│  │    │        └ secret — 32 random bytes, base64url
│  │    └ public id — how we find the row; appears in logs
│  └ environment — live or test
└ vendor prefix — makes keys greppable in your codebase
```

Es decir: el prefijo del proveedor (`fx_`) hace que las claves se puedan buscar con
grep en tu código; el entorno es `live` o `test`; el id público es cómo encontramos
la fila y aparece en los logs; y el secreto son 32 bytes aleatorios en base64url.

Dos partes de esto son deliberadas y vale la pena conocerlas.

**El entorno es una etiqueta, no un sandbox.** Las claves `live` y `test` sirven para
distinguir tus configuraciones —una clave `fx_test_` en producción es fácil de detectar
y de buscar—, pero **ambas llegan a brokers reales**. Una clave `test` conectada a una
cuenta con dinero real abre operaciones reales. fxapis no tiene un mercado simulado:
para probar, conecta **cuentas demo** de tu broker (la mayoría las ofrece gratis) y
úsalas hasta que tu integración se comporte bien.

**El prefijo es `fx_`.** Los escáneres de secretos pueden encontrarlo, y tú también:
`grep -r fx_live_ .` antes de un commit es un buen hábito. Si subes una a un
repositorio público, dala por comprometida y rótala. Las claves emitidas antes del
nombre fxapis empiezan con `ow_`; siguen funcionando tal como se emitieron, y su pista
muestra `ow_`, así que busca ambas.

## No podemos recuperar una clave por ti [#we-cannot-recover-a-key-for-you]

Una clave se muestra una sola vez, al crearla. Nunca guardamos la clave en sí, así que
nadie —ni siquiera nosotros— puede volver a leerla. Las claves perdidas se reemplazan,
no se recuperan.

## Alcances [#scopes]

Los alcances (scopes) son por clave. Emite claves con alcance limitado.

| Alcance           | Permite                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accounts:read`   | Listar y leer cuentas, consultar el estado, leer eventos de cuenta, símbolos, instrumentos y sesiones, buscar servidores de brokers; leer el workspace, los planes y el uso del plan (`GET /v1/billing/usage`)                                                                                                                                                                                                                |
| `accounts:write`  | Conectar, poner en línea (una cuenta o muchas con `prepare`), desconectar de línea, reiniciar, desconectar, eliminar, cambiar el modo, reemplazar la contraseña, mover de servidor, volver a sincronizar símbolos                                                                                                                                                                                                             |
| `trading:read`    | Leer posiciones, órdenes y órdenes multicuenta; conciliar; cálculos de margen y de ganancia; listar hooks de TradingView                                                                                                                                                                                                                                                                                                      |
| `trading:reduce`  | Cerrar posiciones, mover sus stops, cancelar órdenes pendientes y waves: nada que abra exposición                                                                                                                                                                                                                                                                                                                             |
| `trading:execute` | Enviar órdenes y órdenes multicuenta, mover órdenes pendientes, crear, editar y rotar hooks de TradingView, y todo lo que permite `trading:reduce`                                                                                                                                                                                                                                                                            |
| `history:read`    | Leer operaciones cerradas e historial de la cuenta. También lee el registro de eventos (`GET /v1/events`).                                                                                                                                                                                                                                                                                                                    |
| `billing:read`    | Leer la suscripción, las facturas, los cargos por uso, el acuerdo, el estado de pago y el uso diario (`GET /v1/billing/subscription`, `/billing/invoices`, `/billing/invoices/{id}`, `/billing/usage-charges`, `/billing/agreement`, `/billing/standing`, `/billing/usage/daily`). No se ofrece a las apps conectadas. Una clave creada antes del 21 de octubre de 2026 que tiene `accounts:read` sigue leyendo esto con ella |
| `webhooks:write`  | Crear, cambiar, probar y eliminar endpoints de webhooks, y leer sus registros de entrega; consulta [Webhooks](/guides/webhooks)                                                                                                                                                                                                                                                                                               |
| `keys:manage`     | Crear, renombrar, cambiar el alcance y revocar las claves de este workspace. No se puede otorgar a una clave                                                                                                                                                                                                                                                                                                                  |
| `members:manage`  | Invitar, cambiar el rol y quitar miembros. Solo lo tiene un owner o admin con sesión iniciada                                                                                                                                                                                                                                                                                                                                 |
| `billing:manage`  | Elegir, pagar, cambiar y cancelar el plan. Solo lo tiene el owner con sesión iniciada                                                                                                                                                                                                                                                                                                                                         |
| `admin`           | Todo, incluida la gestión de claves. No se puede otorgar a una clave                                                                                                                                                                                                                                                                                                                                                          |

Una clave con `admin` pasa todas las comprobaciones de alcance, y por eso a ninguna
clave se le puede dar. Las claves las crea un owner o admin con sesión iniciada —en la
consola, o con `/v1/api-keys` desde esa sesión—, nunca otra clave.

El alcance no es propiedad. Tener `accounts:write` te permite escribir en las cuentas
*que tu tenant posee*: la cuenta de otro tenant no está prohibida, **no se encuentra**.
Responder 403 ahí confirmaría que un id adivinado existe.

## Límites [#limits]

Los alcances deciden *qué* puede hacer una clave; los límites deciden *cuánto* puede
abrir. Configúralos al crear una clave, o después: en la consola, en **API keys →
Limits**, o con `limits` en `POST /v1/api-keys` y
`PATCH /v1/api-keys/{id}`:

```json
{
  "limits": {
    "maxVolume": "1.00",
    "symbols": ["EURUSD", "XAUUSD"],
    "accountIds": ["…"],
    "maxOpeningOrdersPerDay": 100
  }
}
```

| Límite                   | Significa                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `maxVolume`              | Lotes por orden de apertura. Una orden multicuenta se comprueba por cuenta.                                                                                                                                                                                                                                                                                                                                                                                            |
| `symbols`                | Los símbolos del broker o los instrumentos que puede abrir, sin distinguir mayúsculas. `XAUUSD` permite el oro indicado por instrumento. Las órdenes enviadas con un `symbol` del broker, incluidas las alertas de hooks de TradingView, se comparan con ese símbolo del broker, así que incluye también el nombre del broker (por ejemplo, `GOLD`) si el broker no lo llama `XAUUSD`.                                                                                 |
| `accountIds`             | Las cuentas en las que puede abrir.                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `maxOpeningOrdersPerDay` | Órdenes de apertura desde las 00:00 UTC. Cada cuenta de una orden multicuenta cuenta como una, incluida una que aún espera enviarse en una orden que todavía no salió; las órdenes que nunca salieron (`failed`) no cuentan. El cupo es exacto, incluso para órdenes enviadas en el mismo instante. Una orden cuenta en el día UTC en que se creó: una orden multicuenta creada a las 23:50 UTC y enviada a las 00:10 cuenta para el día en que se creó, una sola vez. |

Omite un campo para no tener límite; `"limits": null` los quita todos. Los límites se
aplican a cada orden de apertura que envía la clave: por la API, en una orden
multicuenta (se comprueba al crearla y otra vez justo antes de enviarla), en un hook de
TradingView que creó la clave, o en un agente de IA que usa la clave por MCP. Una orden
rechazada responde `403 KEY_LIMIT_EXCEEDED`, con `details` indicando el límite, lo que
se pidió y lo que está permitido. **Cerrar, cancelar y mover stops nunca está
limitado**, y un miembro que trabaja en la consola no es una clave, así que ningún
límite lo afecta. (Una app conectada mediante inicio de sesión, por MCP, se controla
más estrictamente: todo lo que cambia, incluidos cierres y stops, se limita a las
cuentas elegidas al conectarla. Consulta [Servidor MCP](/es/guides/mcp#safety-model)).
Una clave con límites solo puede cambiar, rotar o volver a activar los hooks de
TradingView que creó. Si una clave conoció la URL de un hook antes de recibir límites
—por ejemplo, rotó el hook de un compañero—, esa URL sigue operando como el creador del
hook; rota el hook para retirar la URL.

Buenos usos: la clave de un evaluador de prop firm limitada al tamaño de lote máximo
de la cuenta; la clave de un agente de IA que puede operar dos símbolos en una cuenta
demo.

## Gestionar claves [#managing-keys]

Desde la consola (un owner o admin), o con `/v1/api-keys` y una
[clave de administrador](#admin-keys). Las claves normales no pueden gestionar claves:

* **Crear** devuelve la clave en `key`, una sola vez. No se guarda, así que no puede
  volver a mostrarse; la respuesta lleva `Cache-Control: no-store`.
* **Listar y leer** muestran una pista (`fx_live_7f3a9c21_…`), los alcances y cuándo
  se usó la clave por última vez, al minuto; nunca la clave.
* **Renombrar y cambiar el alcance** conservan la clave en sí, así que nada que la use
  tiene que volver a desplegarse. Los nuevos alcances se aplican desde su siguiente solicitud.
* **Revocar** la rechaza desde la siguiente solicitud, se puede repetir sin riesgo y no
  se puede deshacer. Lo que la clave configuró se detiene con ella: una orden
  multicuenta que creó y que no se ha enviado se abandona, y un hook de TradingView
  que creó se detiene por completo, incluidas las alertas de salida (cierre). Así que
  revoca una clave solo después de mover sus hooks, o cierra sus posiciones de otra
  manera.

`admin`, `keys:manage`, `members:manage` y `billing:manage` no se pueden poner en una clave de esta forma, ni
siquiera con una clave de administrador. Una clave que pudiera crear claves podría crearse una más poderosa. Un
workspace tiene como máximo 50 claves sin revocar; una clave vencida cuenta hasta que se revoca.

## Claves de administrador [#admin-keys]

Una clave de administrador permite que tus propias herramientas —un script de
aprovisionamiento, Terraform, un rotador de secretos— gestionen las API keys de este
workspace sin una persona en la consola. Es un tipo de clave aparte, con su propio
prefijo:

```
fx_admin_4c1e9f0a_ZmQ4YmE2MjNhOTg3ZmUxMGJjNGQ...
```

* **Gestiona claves y nada más.** Puede listar, crear, leer, renombrar, cambiar el
  alcance, cambiar los límites y revocar las claves normales del workspace
  (`/v1/api-keys`). Cualquier otra ruta de `/v1` responde `403 ADMIN_KEY_NOT_ALLOWED`:
  trading, cuentas, webhooks, eventos, miembros, facturación y el propio workspace.
  Las rutas fuera de `/v1`, incluida `/mcp`, responden `401 UNAUTHENTICATED`.
  Una clave normal, tenga los alcances que tenga, recibe `403 ADMIN_KEY_REQUIRED` en
  `/v1/api-keys`.
* **No puede tocar claves de administrador.** No las ve, y las claves que crea tienen
  solo los alcances que puede tener cualquier clave. Una clave que creó la nombra en
  `createdByAdminKey`.
* **Solo el owner crea o revoca una.** Esto se hace en la consola, en API keys, después
  de confirmar que eres tú. No hay API para esto. Puede haber como máximo cinco
  activas, y el owner recibe un correo cada vez que se crea o se revoca una.
* **Puedes limitar desde dónde se usa.** Dale direcciones IP o rangos (IPv4 o IPv6,
  como `203.0.113.7` o `2001:db8::/32`). Desde cualquier otro lugar responde
  `403 ADMIN_KEY_IP_NOT_ALLOWED`.
* **Puedes darle una fecha de vencimiento.** Después de ese día responde
  `401 ADMIN_KEY_EXPIRED`. Los límites de direcciones y el vencimiento se definen al
  crear la clave y no se pueden cambiar después.
* **Cada solicitud que hace queda registrada** en el registro de auditoría de fxapis,
  con la ruta, la respuesta y la dirección. El staff de fxapis puede ver ese registro;
  todavía no hay una vista del registro de auditoría para clientes. Las solicitudes
  rechazadas también se registran, pero un rechazo que se repite se registra como
  máximo una vez por minuto por clave y motivo.
* **Revocar una clave de administrador no revoca las claves que creó.** Revócalas
  también si deben detenerse.
* **La verificación adicional no aplica.** A ninguna clave de administrador se le pide
  confirmar. Una clave de administrador incorrecta, desconocida o revocada recibe el
  mismo `401 UNAUTHENTICATED` que cualquier otra clave.

En los SDKs, la gestión de claves está bajo `admin`:

* TypeScript, desde la 0.2.0: `new Fxapis("fx_admin_…").admin.keys.list()`.
* Python, desde la 0.1.6: `Fxapis(api_key="fx_admin_…").admin.keys.list()`.

## Rotación [#rotation]

Las claves son independientes, así que rotarlas no requiere tiempo de inactividad:

1. Crea la clave nueva.
2. Despliégala.
3. Confirma el tráfico en la clave nueva: su `lastUsedAt` en `GET /v1/api-keys`
   (se actualiza como máximo una vez por minuto).
4. Revoca la anterior.

La revocación surte efecto en la siguiente solicitud. No hay caché que esperar.

## Fallos [#failures]

Cada fallo de autenticación devuelve el mismo cuerpo:

```json
{
  "error": { "code": "UNAUTHENTICATED", "message": "A valid API key is required." },
  "requestId": "3f8a..."
}
```

Mal formada, desconocida, secreto incorrecto, revocada, vencida: una sola respuesta
para todas. Decirte *cuál* permitiría a alguien con una lista de claves candidatas
separar las reales de las falsas. Nuestros logs registran la diferencia; la respuesta no.

Una clave que se autentica pero no tiene el alcance recibe `MISSING_SCOPE` (403) en su
lugar, que sí nombra el alcance que falta: para entonces ya demostraste que tienes una
clave válida, y un mensaje útil no cuesta nada.

## Sesiones de miembros [#member-sessions]

La consola no usa una API key y nunca pone una en el navegador. Un miembro inicia
sesión con un correo y una contraseña en `/auth`, y la cookie de sesión que vuelve
se acepta bajo `/v1` en lugar de una clave.

Se resuelve en lo mismo que una clave: un tenant y un conjunto de alcances. Así, a un
miembro lo controlan exactamente las mismas comprobaciones, y la cuenta de otro tenant
es `404` para él igual que para una clave. Los alcances vienen de su rol en el tenant,
no de una lista en una clave:

| Rol      | Alcances                                                                                                                         |
| -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `owner`  | los alcances de lectura, `accounts:write`, `trading:reduce`, `webhooks:write`, `keys:manage`, `members:manage`, `billing:manage` |
| `admin`  | los alcances de lectura, `accounts:write`, `trading:reduce`, `webhooks:write`, `keys:manage`, `members:manage`                   |
| `member` | `accounts:read`, `trading:read`, `history:read`, `billing:read`                                                                  |

La consola no puede abrir una operación directamente. Puede cerrar posiciones, mover
stops y cancelar lo que aún no ha ocurrido; abrir exposición se hace con una clave,
desde tu propio código, o con un [hook de TradingView](/es/guides/tradingview), que un
owner o admin puede crear y que abre operaciones a partir de alertas.

Ningún rol tiene `admin`. Ese alcance pasa todas las comprobaciones y no se puede
otorgar por la API pública; una sesión de navegador es el último lugar donde ponerlo.

Algunas cosas son distintas a una clave, a propósito:

* **Una clave siempre gana.** Una solicitud con un encabezado `Authorization` se juzga
  solo como clave. Una clave incorrecta no recurre a una cookie enviada junto a ella,
  y una clave con alcance limitado no toma prestados los alcances de la cookie de un owner.
* **Las solicitudes entre sitios se rechazan.** Un navegador adjunta una cookie por su
  cuenta, algo que nadie hace con una clave. Una solicitud que cambia el estado con una
  sesión cuyo `Origin` no es la consola recibe `403 UNTRUSTED_ORIGIN`.
* **Cerrar sesión surte efecto en la siguiente solicitud.** No hay una sesión en caché
  que esperar, por la misma razón que revocar una clave no la tiene.
* **Una sesión dura siete días desde el inicio de sesión, y termina tras un día sin
  uso.** Nunca se extiende; volver a iniciar sesión crea una nueva. En **Security**, en
  la consola, los miembros ven cada navegador donde tienen la sesión iniciada, pueden
  cerrar la sesión de cualquiera y cambiar su contraseña, lo que siempre cierra todas
  las demás sesiones y se les notifica por correo.
* **Los cambios sensibles te piden confirmar que eres tú.** Crear una clave que pueda
  mover dinero o cuentas (`trading:execute`, `trading:reduce` o `accounts:write`),
  ampliar una clave a uno de esos alcances o cambiar los límites de una clave que ya
  los tiene, invitar, cambiar un rol, quitar a alguien y cambiar el plan o el pago
  necesitan una confirmación de las últimas dos horas: el código de la app de
  autenticación si tienes la verificación en dos pasos activada; si no, la contraseña.
  Una clave de solo lectura, reducir los alcances de una clave y renombrarla nunca
  lo piden. Iniciar sesión cuenta. Sin ella, la API responde `403 STEP_UP_REQUIRED`,
  con `details[0].method` (`totp` o `password`), y la consola lo pide y continúa. A una
  clave nunca se le pide. El staff mantiene una ventana de diez minutos en la consola
  del staff.
* **Las contraseñas incorrectas repetidas se frenan.** Tras tres para una cuenta, o
  desde una misma red, la página de inicio de sesión te pide pasar una verificación
  rápida; tras diez en quince minutos, la cuenta se pausa quince minutos y su owner
  recibe un correo. Restablecer la contraseña quita la pausa.
* **La verificación en dos pasos pertenece a la sesión.** Activarla o desactivarla, o
  generar nuevos códigos de respaldo, cierra todas las demás sesiones. Desactivarla
  requiere el código actual además de la contraseña. No hay "confiar en este dispositivo".
* **El tráfico de la consola no se mide** como llamadas a la API, y tiene sus propios
  límites de frecuencia, así que revisar tu uso no consume uso ni gasta el margen que
  necesitaba tu integración.

Cualquiera puede registrarse con un correo y una contraseña, y se convierte en el owner
de un workspace nuevo. Empieza una prueba gratuita de 14 días del plan elegido en la
página de precios (Production si no se eligió ninguno; Enterprise no tiene prueba): las
funciones y los límites de ese plan, solo cuentas demo (como máximo 5 durante la
prueba), sin tarjeta, una vez por persona. Pagar el plan lo conserva y permite conectar
cuentas reales; una prueba que termina sin pagar deja la cuenta sin plan. Un registro
que no recibe prueba empieza sin plan hasta que elija uno. No hay plan gratuito. Los
registros pueden cerrarse por un tiempo; entonces la API responde `SIGNUPS_CLOSED`
(una invitación sigue funcionando). Todavía no se ofrece el inicio de sesión con GitHub
ni con Google.

## Miembros [#members]

Un workspace puede tener varias personas, y todas ven las mismas cuentas, claves y uso:

|                                         | Owner            | Admin   | Member |
| --------------------------------------- | ---------------- | ------- | ------ |
| Leer cuentas, órdenes, uso              | ✓                | ✓       | ✓      |
| Cerrar, mover stops, cancelar           | ✓                | ✓       |        |
| Gestionar claves                        | ✓                | ✓       |        |
| Crear y revocar claves de administrador | ✓                |         |        |
| Gestionar hooks de TradingView          | ✓                | ✓       |        |
| Elegir y pagar el plan                  | ✓                |         |        |
| Invitar                                 | admins y members | members |        |
| Cambiar roles                           | ✓                |         |        |
| Quitar                                  | admins y members | members |        |

Nadie cambia ni quita al owner, y nadie actúa sobre sí mismo. A las personas las
gestionan personas. Cada ruta de `/v1/members` rechaza API keys y claves de
administrador, y ninguna está en los SDKs ni en la colección de Postman. La referencia
de la API las marca como "Console only".

**Las invitaciones** se envían por correo a la dirección, y el enlace también se
devuelve, para enviarlo de otra forma. `POST /v1/members/invitations/{id}/resend` lo
vuelve a enviar (como máximo una vez por minuto). Invitar a una dirección que ya tiene
una invitación abierta devuelve esa misma —el mismo enlace— en lugar de una segunda. Un
enlace funciona una vez, vence a los siete días y convierte a quien lo tiene en miembro
de ese workspace con ese rol; nada de lo que envíe puede cambiar ninguno de los dos. El
enlace es una firma sobre el id de la invitación, así que no se guarda en ningún lugar
de donde pudieran robarlo.

**Quitar** a un miembro cierra su sesión en todas partes en su siguiente solicitud,
borra su contraseña y revoca cada API key que creó en la consola: todo lo que siga
usando esas claves recibe `401` desde su siguiente solicitud. Cada revocación queda en
el registro de auditoría, y el owner recibe la lista por correo. Las claves creadas por
cualquier otra persona, creadas con una clave de administrador o creadas antes de que
las claves registraran a su creador (`createdBy` es `null`) no se tocan. Lo que hizo
sigue atribuido a esa persona. La suspensión por parte del staff de fxapis revoca las
mismas claves, y levantarla no las recupera. Si un owner es suspendido o pasa a otro
rol, también se revocan las claves de administrador que creó; las claves que esas
claves de administrador crearon siguen funcionando.

**Bajar** a un admin a member revoca las mismas claves, en el mismo cambio: los members
no pueden crear claves, así que ninguna que haya creado un admin puede sobrevivir al
rol. Cada revocación se audita y el owner recibe la lista por correo, como en una
eliminación; `PATCH /v1/members/{id}` devuelve cuántas se revocaron (`keysRevoked`), y
`GET /v1/members` muestra cuántas revocaría la bajada o la eliminación de cada persona
(`keysCreated`). Hacer admin a un member no revoca nada. Un rol cambiado por el staff de
fxapis sigue la misma regla.

Una persona pertenece a un workspace: una dirección que ya tiene una cuenta no puede
ser invitada a otro.
