# Cuentas

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

> Cómo conectar cuentas de MT5, mantenerlas en línea y qué significa cada estado.



Una cuenta es un login de MT5 que conectaste a fxapis. Su **estado** te dice si
puede operar ahora mismo; su **modo** decide cuándo está en línea.

## Modos [#modes]

Se define al conectar la cuenta y se puede cambiar en cualquier momento con
[`POST /mode`](#post-v1accountsidmode).

| Modo             | En línea                                                                                                                                                                          | Primera orden                    | Ideal para                                                                                         |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------- |
| `always_on`      | Una vez puesta en línea, se queda en línea: nunca se desconecta por inactividad, y vuelve sola en minutos si su terminal se detiene (un login rechazado o la 2FA te esperan a ti) | Inmediata                        | Cuentas que deben actuar al instante en que algo ocurre: señales copiadas, una apertura de mercado |
| `warm_on_demand` | Cuando operas, y luego se desconecta sola cuando está inactiva                                                                                                                    | Tras una conexión breve          | La mayoría de las integraciones y los servicios de señales                                         |
| `cold`           | Solo cuando lo pides                                                                                                                                                              | Después de que la pones en línea | Cuentas que operas según un horario                                                                |

`warm_on_demand` es el valor razonable (el valor predeterminado de la API es `cold`,
así que defínelo). La primera orden tras un rato tranquilo espera mientras la cuenta se
conecta —unos 10 segundos según nuestra medición— y cada orden posterior es inmediata.
Para evitar incluso esa espera, pon las cuentas en línea con anticipación con
[`POST /v1/accounts/prepare`](/signals).

Un cambio de modo se aplica la próxima vez que la cuenta se pone en línea. Para aplicar
`always_on` de inmediato, pon la cuenta en línea después de cambiarlo.

### Ventanas de inactividad, llamadas del conector y estacionamiento [#idle-windows-connector-calls-and-parking]

* Una terminal `warm_on_demand` se detiene tras la ventana de inactividad del plan: 15
  minutos, salvo que el plan diga otra cosa.
* Una llamada del conector (MCP) que nombra la cuenta, o cualquier llamada del conector
  mientras su terminal está en marcha, cuenta como uso, igual que una orden.
* En los planes que estacionan cuentas (tras el número de días del plan), una cuenta sin
  órdenes, llamadas del conector ni arranques durante ese tiempo queda estacionada: su
  terminal se detiene, su modo pasa a `cold` y `stateDetail` lo indica. Sus credenciales
  se conservan. [`POST /v1/accounts/{id}/warm`](#post-v1accountsidwarm) o
  [`POST /v1/accounts/prepare`](/signals) la recuperan como `warm_on_demand`, y una orden
  en ella responde `409 ACCOUNT_NOT_READY` hasta entonces.

## Estados [#states]

Tu código puede actuar según cuatro grupos. Los valores exactos son los que devuelve la API.

**En línea: puede operar**

| Estado      | Significado                                           |
| ----------- | ----------------------------------------------------- |
| `ready`     | En línea y aceptando órdenes.                         |
| `executing` | En línea; se está enviando una orden en este momento. |

**Conectando: espera**

| Estado                                   | Significado                                                                                                                                 |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `provisioning`, `starting`, `connecting` | Poniéndose en línea e iniciando sesión en el broker.                                                                                        |
| `synchronizing`                          | Sesión iniciada; los precios todavía están llegando. Las órdenes se rechazan hasta `ready`, para que ninguna salga con precios incompletos. |
| `reconnecting`                           | La conexión con el broker se cayó y se está restableciendo.                                                                                 |
| `degraded`                               | En línea pero con problemas: precios lentos o desactualizados. Normalmente se recupera sola; [reiníciala](#post-v1accountsidrestart) si no. |

**Fuera de línea: sin conexión con el broker en este momento**

| Estado    | Significado                                                                                                                                                              |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `created` | Conectada, todavía nunca puesta en línea.                                                                                                                                |
| `standby` | Fuera de línea y se sabe que funciona. Una cuenta `warm_on_demand` se pone en línea con su siguiente orden; cualquier cuenta se pone en línea cuando lo pides (`/warm`). |
| `cooling` | Desconectándose.                                                                                                                                                         |
| `offline` | Desconectada (la contraseña guardada se borró), o su terminal dejó de responder (la contraseña se conserva: vuelve a ponerla en línea).                                  |

**Requiere atención: una persona debe corregir algo**

| Estado                | Significado                                                                                                   | Qué hacer                                                                                                                                                                       |
| --------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_credentials` | El broker rechazó el inicio de sesión: una contraseña incorrecta, *o un login que no existe en ese servidor*. | Revisa `problem.otherServers` y prueba el más probable con `POST /v1/accounts/{id}/server`; o envía la contraseña **de trading** corregida a `POST /v1/accounts/{id}/password`. |
| `trading_disabled`    | El broker desactivó el trading para este login.                                                               | Pide al broker, o al dueño de la cuenta, que active el trading. (Una contraseña de inversor, en cambio, llega a `ready` y sus órdenes se rechazan).                             |
| `needs_2fa`           | La cuenta requiere un segundo factor.                                                                         | Desactiva la verificación en dos pasos para esta cuenta, o usa otra.                                                                                                            |
| `needs_certificate`   | El broker requiere un certificado de cliente.                                                                 | Contáctanos.                                                                                                                                                                    |
| `error`               | Algo temporal salió mal.                                                                                      | Se puede reintentar: vuelve a ponerla en línea.                                                                                                                                 |

Los cuatro primeros no mejoran con reintentos, y los inicios de sesión fallidos
repetidos son la forma en que un broker bloquea una cuenta. Por eso dejamos de
intentarlo: poner en línea una de estas cuentas devuelve **409** hasta que se corrija
la causa.

### Qué está mal, en palabras: `problem` [#what-is-wrong-in-words-problem]

Cada cuenta lleva `problem`: `null` mientras está bien o en camino, y en otro caso qué
está mal y cómo corregirlo, lo mismo que muestra la consola.

```json
"problem": {
  "code": "LOGIN_REFUSED",
  "title": "The broker refused the login",
  "explanation": "JustMarkets-Demo3 did not accept login 2002126135 with this password. Either the password is not the account's trading password …, or this login does not exist on JustMarkets-Demo3 …",
  "detail": "the broker refused the login on mt5ldn5.srip.net:8750: -6 Terminal: Authorization failed",
  "otherServers": ["JustMarkets-Demo", "JustMarkets-Demo2", "JustMarkets-Live"],
  "actions": [
    { "kind": "switch_server", "server": "JustMarkets-Demo" },
    { "kind": "switch_server", "server": "JustMarkets-Demo2" },
    { "kind": "replace_credentials" }
  ]
}
```

Un broker responde "authorization failed" tanto para una contraseña incorrecta como para
un login que vive en otro servidor, y los brokers tienen varios servidores con nombres
casi idénticos. `otherServers` lista los otros servidores del broker, del más probable
al menos: servidores en los que han iniciado sesión cuentas aquí, luego el servidor
principal del broker y luego los nombres más parecidos. Muéstraselos a tu usuario, o
prueba el primero con `POST /v1/accounts/{id}/server`: reutiliza la contraseña guardada.

Cuando una terminal no encuentra el servidor de la cuenta —un nombre que no es un
servidor de MT5, como la etiqueta que un broker usa para un tipo de cuenta—, una cuenta
que lo intentó y nunca inició sesión lleva `"code": "SERVER_NOT_FOUND"`, con los
servidores reales del broker en `otherServers` y una acción `switch_server` para cada
uno. `POST /v1/accounts/{id}/server` con el correcto conserva la contraseña guardada.
Escribe el servidor exactamente como lo muestra el diálogo File → Login de MetaTrader o
el correo de bienvenida del broker.

Cuando las cuentas no pueden ponerse en línea por un problema de nuestro lado, las
cuentas en camino a estar en línea (`created`, `standby`, `starting`, `offline`,
`error`) llevan `"code": "PLATFORM_ISSUE"` sin `actions`: no hay que cambiar nada de la
cuenta, y reintentar no ayudará. Un `POST /v1/accounts/{id}/warm` fallido dice lo mismo
en su mensaje. Se resuelve solo una vez que se corrige;
[status.fxapis.com](https://status.fxapis.com) tiene las novedades. Un login
rechazado, la 2FA, un certificado o el trading desactivado conservan sus propios
códigos: esos vienen del broker.

### Alertas en la consola [#alerts-in-the-console]

Cuando una cuenta entra en uno de los estados anteriores, la consola abre una alerta: la
campana en la parte superior de cada página de la consola cuenta las que no has leído,
**Notifications** las lista con lo que dijo el broker y la única corrección (en la
página de la cuenta, donde está en la tarjeta del problema), y la página de la cuenta
muestra la misma tarjeta. Una alerta se cierra sola cuando la cuenta sale de ese
estado; las resueltas siguen en la lista una semana. Un `error` solo se muestra si dura
dos minutos: la mayoría se resuelven en segundos. Todos en el workspace las ven; solo
los owners y admins pueden hacer la corrección. Solo dentro de la app: no se envía nada
por correo y no hay API para ellas; las integraciones usan el webhook
`account.state_changed` o `problem`.

### `POST /v1/accounts/{id}/server` [#post-v1accountsidserver]

Mueve la cuenta a otro servidor, **conservando la contraseña guardada**: para un login
agregado con el nombre de servidor equivocado, así nadie vuelve a escribir la
contraseña. Con `connect: true` (el valor predeterminado) se pone en línea de inmediato
y la respuesta llega en segundos; consulta la cuenta o sus eventos. **409**
`ACCOUNT_EXISTS` cuando ese login ya está conectado en ese servidor; **409**
`NO_PASSWORD` cuando no hay contraseña guardada (usa `/password`).

```bash
curl -X POST https://api.fxapis.com/v1/accounts/$ID/server \
  -H "Authorization: Bearer $FXAPIS_KEY" -H "content-type: application/json" \
  -d '{"server":"JustMarkets-Demo"}'
```

### `GET /v1/brokers/servers` [#get-v1brokersservers]

Un selector de servidores para tu propio formulario de conexión, para que quienes
conectan elijan su servidor en lugar de escribirlo exactamente. Busca por lo que
escriben —el nombre de un broker (`vantage`), el inicio de un servidor
(`JustMarkets-De`), con o sin guiones y espacios— desde dos caracteres, con debounce:

```bash
curl "https://api.fxapis.com/v1/brokers/servers?q=justmarkets" -H "Authorization: Bearer $FXAPIS_KEY"
```

```json
{ "data": [
  { "name": "JustMarkets-Demo", "company": "Just Global Markets Ltd.", "kind": "demo", "proven": true },
  { "name": "JustMarkets-Live", "company": "Just Global Markets Ltd.", "kind": "live", "proven": false }
] }
```

Primero vienen los servidores en los que han iniciado sesión cuentas en fxapis
(`proven`), luego los nombres que empiezan con lo escrito, luego el tipo pedido y luego
el servidor principal del broker. También se encuentra un broker que nadie ha usado aquí
todavía: con menos de cinco coincidencias y al menos tres caracteres escritos, se
consulta una vez la búsqueda de brokers (esa respuesta puede tardar uno o dos
segundos), y una búsqueda que no encontró nada no se repite durante 24 horas. `limit`
define cuántos se devuelven (1–50, 20 por defecto). **Deja siempre que la gente use
exactamente lo que escribió**: un servidor que no aparece en la lista se puede conectar
igual. Sin `q`, devuelve los servidores más usados aquí.

### `GET /v1/accounts/{id}/events` [#get-v1accountsidevents]

El historial de la cuenta en palabras, del más reciente al más antiguo —agregada,
iniciando sesión, rechazada por el broker, en línea, movida a otro servidor,
desconectada—, cada uno con un `tone` (`success`, `info`, `warning`, `danger`), un
`title`, un `detail` opcional y quién lo hizo (`key`, `member`, `staff`, `system`). La
lista de actividad de la consola es este endpoint. `limit` hasta 200 (50 por defecto).

## Endpoints [#endpoints]

Las formas completas de solicitudes y respuestas están en la
[referencia de la API](/api-reference). Lo que sigue es lo que la referencia no puede
decirte.

### `POST /v1/accounts` [#post-v1accounts]

Conecta la cuenta y guarda su contraseña, cifrada. Todavía no inicia sesión.

El mismo `login` y `server` solo se pueden conectar una vez por workspace —una segunda
copia significaría dos lugares capaces de operar el mismo dinero—, así que un duplicado
se rechaza con **409** mientras siga conectado. Un login que desconectaste antes se
vuelve a conectar en su lugar: consulta [`/disconnect`](#post-v1accountsiddisconnect).

Si la contraseña no se puede guardar de forma segura, la cuenta **no** se crea y recibes
**503**, en lugar de una cuenta que nunca podría ponerse en línea.

### `POST /v1/accounts/{id}/warm` [#post-v1accountsidwarm]

Pone la cuenta en línea. Devuelve **202** de inmediato con un `pollUrl`; consúltalo
hasta que el estado sea `ready`.

Se puede llamar repetidamente sin riesgo: para una cuenta que ya está en línea devuelve
`alreadyRunning: true` y no hace nada más.

### `POST /v1/accounts/{id}/cool` [#post-v1accountsidcool]

Desconecta la cuenta. Sigue conectada a fxapis, en `standby`, y vuelve con la siguiente
orden o cuando lo pides. Funciona desde cualquier estado: a una cuenta en `created` o
en un estado que requiere atención y que todavía tiene una terminal en marcha se le
detiene, y conserva el estado que indica lo que aún necesita.

**Se rechaza con 409 mientras se envía una orden**: detenerse a mitad de una orden
dejaría su resultado incierto. Espera un momento e inténtalo de nuevo.

Las posiciones abiertas no se ven afectadas. Los stop loss y take profit viven en el
broker y siguen funcionando mientras la cuenta está fuera de línea.

### `POST /v1/accounts/{id}/restart` [#post-v1accountsidrestart]

Desconecta la cuenta y la vuelve a poner en línea: para una cuenta que está en línea
pero se comporta mal (`degraded`, precios desactualizados). El mismo **409** mientras
hay una orden en curso.

### `POST /v1/accounts/{id}/disconnect` [#post-v1accountsiddisconnect]

Desconecta la cuenta **y borra la contraseña guardada.** La cuenta y su historial se
conservan, en `offline`. Para volver a conectarla, envía el mismo login y servidor a
`POST /v1/accounts` con la contraseña: vuelve la misma cuenta, con **200**.

Úsalo cuando un cliente se va. Una contraseña que ya no necesitas es una que nosotros
ya no deberíamos guardar.

### `DELETE /v1/accounts/{id}` [#delete-v1accountsid]

Elimina la cuenta para siempre: su terminal se detiene, su contraseña se borra y el
registro se va con sus órdenes, deals y posiciones. **No se puede deshacer**:
desconéctala en su lugar si quieres que el historial siga siendo legible. La respuesta
indica cuánto se eliminó con ella.

Se rechaza con **409** mientras hay una orden en curso (`ACCOUNT_EXECUTING`), mientras
una orden multicuenta que la incluye no ha terminado (`ACCOUNT_IN_WAVE`), y cuando
nuestra última revisión encontró posiciones abiertas (`ACCOUNT_HAS_POSITIONS`). Las
posiciones abiertas siguen abiertas en el broker con sus stops, pero una vez eliminada
la cuenta no se pueden mostrar ni cerrar aquí: ciérralas primero, o envía
`?force=true` para eliminarla de todos modos.

Los hooks de alertas dejan de enviar a la cuenta, y un hook que se queda sin cuentas se
apaga. El uso de este mes no se ve afectado. El mismo login y servidor se pueden volver
a conectar después, como una cuenta nueva con un id nuevo.

### `POST /v1/accounts/{id}/password` [#post-v1accountsidpassword]

Reemplaza la contraseña guardada: después de que cambió en el broker, o cuando la
cuenta está en `invalid_credentials`. Agrega `server` para corregir el nombre del
servidor. Cualquier terminal en marcha se detiene primero, y se espera a que termine
(**409** mientras hay una orden en curso); la cuenta queda en `created`. Luego ponla en
línea con `POST /v1/accounts/{id}/warm` y consulta el estado: eso es un inicio de sesión
nuevo con la nueva contraseña. No hace falta desconectar nada entre medio.

### `POST /v1/accounts/{id}/mode` [#post-v1accountsidmode]

Cambia el modo. Se aplica la próxima vez que la cuenta se pone en línea.

### `GET /v1/accounts/{id}/status` [#get-v1accountsidstatus]

El económico, hecho para consultar repetidamente. Cada dos segundos está bien.

### `GET /v1/accounts/{id}/figures` [#get-v1accountsidfigures]

Balance, equity, margen, margen libre, nivel de margen, crédito y ganancia abierta, como
strings decimales en la moneda de la cuenta, leídos de su terminal de MetaTrader.

```bash
curl -sS "$FXAPIS_API/v1/accounts/$FXAPIS_ACCOUNT/figures" -H "Authorization: Bearer $FXAPIS_KEY"
# → { "data": { "accountId": "…", "balance": "10000.50000000", "equity": "10037.75000000",
#      "margin": "120.00000000", "freeMargin": "9917.75000000", "marginLevel": "8364.79166667",
#      "credit": "0.00000000", "profit": "37.25000000", "currency": "USD", "leverage": 500,
#      "marginMode": "hedging", "observedAt": "2026-10-15T12:00:00.120Z", "ageMs": 4210,
#      "source": "snapshot" } }
```

* **Sin `fresh`, responde la última lectura** (`source: "snapshot"`). Mientras la
  cuenta está en línea esa lectura se toma cada 15 segundos, y `observedAt` dice cuándo.
  `GET /v1/accounts/{id}` y la lista de cuentas llevan las mismas cifras, con
  `figuresObservedAt`. Una cuenta nunca leída tiene cifras `null`.
* **Con `fresh=true`, se consulta a la terminal ahora** (`source: "live"`). La cuenta
  debe estar `ready`: fuera de línea, `executing` una orden o `degraded` es
  `409 ACCOUNT_NOT_READY`. Una terminal que todavía corre un worker anterior responde
  `501 CAPABILITY_UNAVAILABLE` en su lugar; es raro en la práctica; mientras tanto, omite
  `fresh` para esa cuenta. Las llamadas dentro del mismo segundo comparten una lectura,
  y solo una lectura que llega a la terminal se descuenta del presupuesto en vivo de la
  cuenta ([Errores](/es/errors#rate-limits)).
* **`marginLevel` es `null` mientras no se usa margen.** El equity sobre un margen nulo
  no está definido; no es cero.
* **`credit` y `profit` se completan para cada cuenta en línea**; `null` solo para una
  nunca leída.
* **`marginMode`** es `netting` (una posición por símbolo) o `hedging` (una por orden),
  `null` hasta que la terminal lo haya informado.
* **Los webhooks no llevan cifras.** `account.state_changed` se dispara con un cambio de
  estado, y el balance y el equity cambian sin uno. Léelos aquí.

## Consultar bien el estado [#polling-well]

```python
import time, httpx

def wait_until_ready(client, account_id, timeout=120):
    """Polls until the account is ready, or until it is clear it will not be."""
    NEEDS_ATTENTION = {"invalid_credentials", "needs_2fa", "needs_certificate", "trading_disabled"}
    deadline = time.monotonic() + timeout

    while time.monotonic() < deadline:
        state = client.get(f"/v1/accounts/{account_id}/status").json()["data"]

        if state["state"] == "ready":
            return state
        if state["state"] in NEEDS_ATTENTION:
            # Not retryable: report the reason now instead of timing out later.
            raise RuntimeError(f"{account_id} needs attention: {state['state']} — {state['detail']}")

        time.sleep(2)

    raise TimeoutError(f"{account_id} did not reach ready within {timeout}s (last: {state['state']})")
```

Dos hábitos que ahorran tickets de soporte:

**Detente ante un estado que "requiere atención".** Consultar durante dos minutos en
`invalid_credentials` no te dice nada que la primera respuesta no te haya dicho.

**Deja más tiempo del que parece necesario.** Unos 10 segundos según nuestra medición, y
un broker ocupado puede tardar más. Un tiempo de espera de 120 segundos no cuesta nada
cuando todo va bien.
