API de tipos de cambio por WebSocket

Suscríbete a pares compatibles y recibe actualizaciones en una conexión persistente. Guarda tu clave API en el servidor.

exchangerate.devAPI de tasas de cambio · Actualizada el 15 sept 2026

Inicia una conexión

Conéctate a wss://api.exchangerate.dev/v1/stream, envía auth en 10 segundos y suscríbete después de authenticated.

Ejemplo de conexión

Esta secuencia del servidor autentica una clave y se suscribe a USD/EUR y USD/JPY.

Node.js 22+ · cliente WebSocket del servidor
// Node.js 22+ · run on your server · set EXCHANGERATE_API_KEY in the environment
const key = process.env.EXCHANGERATE_API_KEY;
if (!key) throw new Error("EXCHANGERATE_API_KEY is required");

let retries = 0;
let stopped = false;
function connect() {
  const ws = new WebSocket("wss://api.exchangerate.dev/v1/stream");
  ws.addEventListener("open", () => {
    ws.send(JSON.stringify({ action: "auth", api_key: key }));
  });
  ws.addEventListener("message", ({ data }) => {
    const frame = JSON.parse(String(data));
    if (frame.type === "authenticated") {
      retries = 0;
      ws.send(JSON.stringify({ action: "subscribe", base: "USD", symbols: ["EUR", "JPY"] }));
    } else if (frame.type === "snapshot" || frame.type === "update") {
      if (frame.stale) return; // Keep the observation time; don't treat it as a fresh tick.
      console.log(frame.base, frame.symbol, frame.rate, frame.effective_at);
    } else if (frame.type === "state") {
      console.log(frame.base, frame.symbol, frame.state); // stale or unavailable
    } else if (frame.type === "error") {
      console.error(frame.code, frame.message);
      if (["invalid_api_key", "quota_exceeded", "connection_limit_exceeded", "subscription_limit_exceeded", "stream_plan_required", "stream_access_changed"].includes(frame.code)) {
        stopped = true;
        ws.close();
      }
    }
  });
  ws.addEventListener("close", () => {
    if (stopped) return;
    const delay = Math.min(30_000, 1_000 * 2 ** Math.min(retries++, 5));
    setTimeout(connect, delay + Math.random() * 250);
  });
}
connect();

Las conexiones WebSocket requieren autenticación.

Lee cada mensaje

Cada mensaje incluye el par, el tipo, la hora de observación y el estado de frescura. Trata unavailable y stale como estados explícitos.

JSON · mensaje de ejemplo; los valores y la hora son ilustrativos
{
  "type": "update",
  "base": "USD",
  "symbol": "JPY",
  "rate": "154.792",
  "effective_at": "2026-09-15T02:59:44Z",
  "source": "live",
  "source_type": "market",
  "market_session": "open",
  "derived": false,
  "stale": false
}

Cobertura

Solo puedes suscribirte a los pares de la tabla de cobertura actual. Los cruces requieren observaciones recientes de ambas patas.

AUD, CAD, CHF, EUR, GBP, JPY, MXN, NOK, NZD, PLN, SEK, SGD, USD, ZAR · 182 Pares compatibles

Las actualizaciones son observaciones indicativas. Comprueba el estado y la hora de observación.

Ver la cobertura actual

Límites del plan

El número de conexiones y de pares por conexión depende del plan. Cada conexión aceptada consume una unidad de cuota mensual.

La tabla muestra límites nuevos. Las cuentas existentes conservan los planes antiguos Basic 3 × 25 o Pro 10 × 100 (conexiones × pares por conexión). El mensaje authenticated indica tus límites efectivos.

PlanConexionesPares por conexiónUso comercial
Free00Sí
Basic00Sí
Plus110Sí
Pro5100Sí

Cada conexión aceptada consume una unidad de cuota mensual.

Ver precios

Uso comercial

Consulta el plan y las condiciones de uso comercial actuales antes de distribuir un producto que dependa del flujo.

Reconecta de forma segura

Tras una desconexión, espera antes de reconectar, autentica de nuevo, espera authenticated y vuelve a suscribirte. Nunca pongas la clave en una URL ni en JavaScript público.

Las actualizaciones que faltan siguen faltando; el flujo no inventa valores.

¿Puedo conectarme sin autenticación?

No. Las conexiones WebSocket requieren una clave API. La evaluación anónima está disponible mediante los endpoints REST compatibles.

¿Se transmite cada par de monedas?

No. La cobertura de WebSocket depende del par. Consulta la tabla y gestiona explícitamente las suscripciones no compatibles.