Autenticación y límites
Los endpoints de datos aceptan evaluación anónima: 10 solicitudes por minuto y 100 por hora e IP. Una clave aplica la cuota mensual de tu cuenta. Los precios de Free llegan con 15 minutos de retraso (cabecera X-Price-Delay-Seconds: 900).
Authorization: Bearer YOUR_KEYX-RateLimit-Remaining: 9999X-RateLimit-Reset: 1788220800Campos que explican la frescura
source indica la clase de fuente, market_session el estado del mercado y data_updated_at la hora de la observación contribuyente más antigua de la respuesta. Guarda los tres.
Endpoints
| GET /v1/latest[/{BASE}] | Tipos actuales, todos o filtrados por symbols. |
| GET /v1/{YYYY-MM-DD}[/{BASE}] | Foto histórica de una fecha y una base. |
| GET /v1/convert/{FROM}/{TO}[/{AMOUNT}] · POST /v1/convert | Convierte un importe; GET individual o POST por lotes. |
| GET /v1/rate/{slug} | Cotización plana de un par por slug. |
| GET /v1/range | Serie diaria con paginación y descargas. |
| GET /v1/currencies | Lista de monedas compatibles; no acepta parámetros. |
| GET /v1/account | Cuenta, plan, clave activa y consumo del mes. |
| GET /v1/indices/{index_slug} · GET /v1/indices/{index_slug}/timeseries | Último valor de los índices USD y sus series históricas. |
Series intradía y cobertura
/v1/timeseries admite 1m, 5m, 15m, 1h, 4h y referencias diarias 1d; no hay 2h. Los cruces SGD sin USD no admiten 4h; USD/SGD y su inverso sí. La recopilación de mercado comenzó el 2026-09-14. Los datos 1m se conservan 30 días; los intervalos mayores no tienen caducidad programada. La retención no garantiza que ya exista toda esa profundidad. La cobertura intradía de 1m a 1h incluye 221 pares únicos: 143 pares USD y 78 cruces.
Los cruces históricos requieren cierres reales del mismo intervalo UTC, separados como máximo 5 segundos. effective_at conserva la observación más antigua. No se rellenan huecos y el intervalo abierto puede cambiar. 1d usa referencias diarias de todo el catálogo. La tabla cuenta pares únicos; se admiten ambos sentidos.
| interval | Pares únicos |
|---|---|
1m | 221 |
5m | 221 |
15m | 221 |
1h | 221 |
4h | 209 |
1d | 10296 |
curl "https://api.exchangerate.dev/v1/timeseries?base=EUR&symbols=JPY&interval=15m&from=2026-09-14T12:00:00Z&to=2026-09-14T13:00:00Z" \ -H "Authorization: Bearer YOUR_API_KEY"Una ventana admitida sin observaciones devuelve HTTP 200 con data: [], has_more: false y next_cursor: null. Un intervalo desconocido devuelve unsupported_interval; un par fuera de cobertura, unsupported_pair_interval y rejected_pairs (HTTP 400). Las solicitudes mixtas se rechazan completas.
Cobertura y límites detallados
API de tipos de cambio intradía
WebSocket en vivo
Conecta a wss://api.exchangerate.dev/v1/stream y envía auth en 10 segundos. Guarda la clave en el servidor, nunca en la URL ni en JavaScript público. No hay conexiones anónimas. Tras authenticated, envía subscribe. El stream usa las monedas de abajo; los cruces requieren observaciones recientes de ambas monedas, separadas como máximo 5 segundos. Pueden aparecer estados unavailable o stale. 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.
AUD, CAD, CHF, EUR, GBP, JPY, MXN, NOK, NZD, PLN, SEK, SGD, USD, ZAR
| Plan | Conexiones simultáneas | Pares por conexión |
|---|---|---|
| Free | 0 | 0 |
| Basic | 0 | 0 |
| Plus | 1 | 10 |
| Pro | 3 | 100 |
{"action":"auth","api_key":"YOUR_KEY"}{"action":"subscribe","base":"EUR","symbols":["USD","JPY"]}Errores
REST: Todos usan { result: "error", code, message }. Un 429 añade Retry-After; no hay datos simulados cuando una fuente falla. HTTP 403 plan_gated incluye tier, interval; si se supera la ventana histórica, también history_days, earliest_allowed. Si una mejora permite la solicitud, incluye upgrade_plans, upgrade_offers (plan, loses) وupgrade_url.
{ "result": "error", "code": "missing_parameter", "message": "required parameter missing: symbols"}{ "result": "error", "code": "plan_gated", "message": "The 15m interval is not included in your plan.", "tier": "plus_2026", "interval": "15m", "upgrade_plans": ["pro_2026"], "upgrade_offers": [{ "plan": "pro_2026", "loses": [] }], "upgrade_url": "https://exchangerate.dev/pricing?plan=pro_2026&source=api&reason=plan_gated"}curl -fsS --max-time 10 "https://api.exchangerate.dev/v1/latest/USD?symbols=EUR,GBP"from urllib.request import Request, urlopenimport json# Identify your application explicitly when calling the API.request = Request("https://api.exchangerate.dev/v1/latest/USD?symbols=EUR,GBP", headers={"User-Agent": "exchangerate-docs/1.0"})with urlopen(request, timeout=10) as response: data = json.load(response)print(data["rates"]["EUR"])const response = await fetch("https://api.exchangerate.dev/v1/latest/USD?symbols=EUR,GBP", { signal: AbortSignal.timeout(10_000),});if (!response.ok) throw new Error(`HTTP ${response.status}`);const data = await response.json();console.log(data.rates.EUR);Guías de integración: Python · JavaScript / Node.js · Google Sheets · Excel · Go · Swift · Zapier