# Opera MetaTrader 5 desde Node.js con el SDK de TypeScript de fxapis

> Instala el SDK de TypeScript de fxapis, conecta una cuenta de MT5, coloca una orden de mercado idempotente y maneja cada falla desde Node.js, sin terminal.

Publicado el 2026-10-26 por ElWizard para fxapis. Canónica: https://fxapis.com/es/blog/api-de-mt5-para-nodejs-sdk-de-typescript

## En resumen

- npm install fxapis te da un cliente tipado para la API alojada de MT5: un método por endpoint, generado a partir de la especificación OpenAPI, sin dependencias en tiempo de ejecución.
- Cuatro llamadas te llevan de un login de MT5 a una orden ejecutada: conectar la cuenta, ponerla en línea, esperar a ready y colocar la orden con una clave de idempotencia.
- Cada falla es un FxapisError con un código estable. ORDER_UNRESOLVED nunca se reenvía; lo reintentable se reenvía con la misma clave de idempotencia.
- Guarda la API key en tu servidor. El SDK es para backends, nunca para un navegador ni una app móvil.

El SDK oficial de TypeScript de fxapis envuelve la API REST alojada de MetaTrader 5 en un cliente pequeño: **un método por endpoint, generado a partir de la especificación OpenAPI de la API, sin dependencias en tiempo de ejecución**. Corre en Node.js 18 o más reciente, se distribuye como ESM con declaraciones de tipos completas y es de código abierto en [github.com/FXapis/fxapis-typescript](https://github.com/FXapis/fxapis-typescript).

No hay ningún terminal de MetaTrader de tu lado. Los terminales corren en la nube de fxapis y tu código hace solicitudes HTTPS, así que el mismo programa corre en una laptop, un servidor Linux o una función serverless. Este artículo cubre cómo instalarlo, las llamadas que te llevan de un login de MT5 a una operación cerrada, y el manejo de errores que importa cuando una orden es dinero real.

## Instálalo

```bash
npm install fxapis
```

Este artículo está escrito para `fxapis` 0.3.1 en npm, la versión actual al 26 de octubre de 2026.

Crea una API key en la [consola](https://fxapis.com/dashboard/keys) y guárdala en una variable de entorno en tu servidor. La clave nunca debe llegar a un navegador ni a una app móvil: cualquiera que la tenga puede operar las cuentas que ve. Mientras construyes, conecta una cuenta **demo** de un broker: toda clave de fxapis, incluidas las de prueba, llega a un broker real.

## De un login de MT5 a una operación cerrada

```ts
import { Fxapis, newIdempotencyKey } from "fxapis";

const fx = new Fxapis(process.env.FXAPIS_API_KEY!);

// 1. Connect the account once. The trading password, not the investor password.
const account = await fx.postAccounts({
  login: "26177561",
  server: "YourBroker-Demo", // exactly as MetaTrader shows it, e.g. Exness-MT5Trial8, ICMarketsSC-Demo or Pepperstone-Demo
  password: process.env.MT5_PASSWORD,
  mode: "warm_on_demand",
});

// 2. Bring it online, and wait for `ready` (about ten seconds for a typical broker).
await fx.postAccountsByIdWarm(account.id);
for (;;) {
  const { state, detail } = await fx.getAccountsByIdStatus(account.id);
  if (state === "ready") break;
  if (["invalid_credentials", "needs_2fa", "needs_certificate", "trading_disabled"].includes(state)) {
    throw new Error(`the account needs attention: ${state} — ${detail}`);
  }
  await new Promise((r) => setTimeout(r, 2000));
}

// 3. A market order, with a key you keep until the order has an answer.
const order = await fx.postAccountsByIdOrdersMarket(
  account.id,
  { symbol: "EURUSD", side: "buy", volume: "0.01" },
  { idempotencyKey: newIdempotencyKey() },
);
console.log(order.state, order.filledPrice);

// 4. Close the position it opened — that position carries the order's own ticket.
await fx.postAccountsByIdReconcile(account.id); // refresh positions now rather than in ~15 s
const positions = await fx.getAccountsByIdPositions(account.id);
const opened = positions.find((p: { brokerPositionId: string }) => p.brokerPositionId === order.brokerOrderId);
if (opened) {
  await fx.postAccountsByIdPositionsByPositionIdClose(account.id, opened.brokerPositionId, {}, {
    idempotencyKey: newIdempotencyKey(),
  });
}
```

Tres detalles de ese código son deliberados:

- **Los volúmenes y los precios son strings**: `"0.01"`, no `0.01`. Un número JSON ya pasó por el punto flotante, y la API lo rechaza en lugar de operar un tamaño que no pediste.
- **Conectar no inicia sesión.** `postAccounts` guarda la cuenta y cifra su contraseña; `postAccountsByIdWarm` responde de inmediato mientras ocurre el inicio de sesión, y tú consultas el estado. Una contraseña equivocada aparece ahí, no en la primera operación.
- **Cada orden y cada cierre llevan una clave de idempotencia.** Si la solicitud se queda sin respuesta, la reenvías con la *misma* clave y recibes la primera respuesta en lugar de una segunda posición. [Órdenes idempotentes](https://docs.fxapis.com/es/guides/idempotency) explica por qué esto importa más de lo que parece.

## Nombres de métodos, parámetros de consulta y páginas

Cada método se llama como su ruta: `getAccounts`, `postAccountsByIdWarm`, `getAccountsByIdPositions`, `postAccountsPrepare` para poner en línea muchas cuentas a la vez. Primero van los parámetros de ruta, luego el cuerpo y luego las opciones. Los parámetros de consulta van en `options.query`, y una lista paginada vuelve como un array con su página adjunta:

```ts
const unknown = await fx.getOrders({ query: { state: "unknown", limit: 50 } });
const next = unknown.page?.nextCursor; // pass it back as `cursor` for the next page
```

Las respuestas son el `data` de la API, sin tipos a propósito: tu código nombra los campos que lee, y la [referencia de la API](https://docs.fxapis.com/api-reference) documenta cada uno (en inglés).

## Cuando una orden no simplemente se ejecuta

Cada falla es un `FxapisError` con un `code` estable, un `message` legible, el `requestId` para darle a soporte, y `retryable`:

```ts
import { FxapisError } from "fxapis";

try {
  await fx.postAccountsByIdOrdersMarket(accountId, body, { idempotencyKey: key });
} catch (err) {
  if (!(err instanceof FxapisError)) throw err;
  if (err.code === "ORDER_UNRESOLVED") {
    // It may be live at the broker. Never resend: poll getOrdersById until it settles.
  } else if (err.code === "ORDER_REJECTED") {
    // The broker refused it and nothing opened. Show err.message. A new attempt needs a NEW key.
  } else if (err.retryable) {
    // SEND_FAILED, ACCOUNT_NOT_READY, RATE_LIMITED, GATEWAY_ERROR …: nothing was done.
    // Wait (err.retryAfter seconds when set) and resend with the SAME key.
  }
}
```

La regla que te protege es la primera rama: `ORDER_UNRESOLVED` significa que nadie sabe todavía si la orden llegó al broker, y `retryable` es false para ese código, sea cual sea lo demás. fxapis confirma una orden de apertura con el historial de deals del propio broker y la saca de `unknown`. Una página de error de un proxy entre tú y fxapis (un 502 o 504 que no es una respuesta de fxapis) llega como `GATEWAY_ERROR`, reintentable con la misma clave, nunca como un error al leer el JSON.

El SDK nunca reintenta por su cuenta. Esa decisión queda en tu código, que sabe para qué era la orden.

## Adónde ir después

- [fxapis-examples](https://github.com/FXapis/fxapis-examples) tiene este inicio rápido, click-to-trade para proveedores de señales y un copiador de operaciones, listos para correr contra una cuenta demo; mira [el artículo de los ejemplos](https://fxapis.com/es/blog/ejemplos-de-api-de-mt5-en-python-nodejs-y-curl).
- El [starter de Next.js](https://github.com/FXapis/fxapis-nextjs-starter) es una app pequeña que funciona sobre este SDK: conecta una cuenta, mira sus posiciones y coloca una operación confirmada.
- [SDKs y ejemplos](https://docs.fxapis.com/es/sdks) en la documentación, y la [guía de Node.js](https://docs.fxapis.com/guides/nodejs) si prefieres ver cada solicitud con `fetch` simple (en inglés).
- [Trading](https://docs.fxapis.com/es/trading) cubre cada resultado que puede tener una orden.

## Preguntas

### ¿Qué versiones de Node.js soporta el SDK de fxapis?

Node.js 18 o más reciente. Es un paquete ESM con declaraciones completas de TypeScript y sin dependencias en tiempo de ejecución: usa el fetch integrado.

### ¿Necesito tener MetaTrader 5 instalado para usarlo?

No. Los terminales de MT5 corren en la nube de fxapis. Tu código solo hace solicitudes HTTPS, así que corre en Linux, macOS, Windows o una función serverless.

### ¿El SDK reintenta por mí las órdenes que fallan?

No, a propósito. Reenviar una orden es decisión tuya: el SDK te dice si es seguro (err.retryable) y tú la reenvías con la misma clave de idempotencia.

### ¿Por qué las respuestas no tienen tipos?

Los métodos devuelven los datos de la API tal cual, así que tu código nombra solo los campos que usa. La referencia de la API documenta cada campo, y la documentación generada de cada método enlaza a ella.
