← Volver a docs
Pro+GET

GET /v1/fx/route

Consulta los 9 mercados disponibles (7 P2P + paralela + BCV) en paralelo y devuelve el mejor mercado para el monto pedido, junto con las alternativas ordenadas de mejor a peor.

Es el endpoint diferenciador de Pro. En lugar de que tu aplicación llame /v1/fx/rates y calcule el mejor precio manualmente, /v1/fx/route lo hace por ti con una sola llamada, incluyendo filtrado por frescura y motivos de descarte por mercado.

Disponible únicamente en el plan Pro y superiores. En planes inferiores devuelve 402 feature_not_in_plan.


Request

GET /v1/fx/route?from=USD&to=VES&amount=1000&direction=send HTTP/1.1
Host: api.cotizave.com
X-API-Key: ctz_live_aB3cD8fG2hJ5kL9mN1pQ4rS7tU0vWxYzA6bC3d

Query parameters

ParámetroTipoRequeridoDefaultDescripción
fromstringMoneda origen: USD o VES
tostringMoneda destino: VES o USD
amountnumberMonto a convertir. Debe ser mayor a 0.
directionstringNosendsend: maximizar VES recibidos (el caller envía USD).receive: minimizar VES pagados (el caller compra USD).
max_stalenessintegerNo0Antigüedad máxima de una cotización en segundos. 0 = sin filtro.

Ejemplos de request

Mejor mercado para enviar 1.000 USD:

curl "https://api.cotizave.com/v1/fx/route?from=USD&to=VES&amount=1000&direction=send" \
  -H "X-API-Key: $COTIZAVE_API_KEY"
const params = new URLSearchParams({ from: 'USD', to: 'VES', amount: '1000', direction: 'send' })
const res = await fetch(`https://api.cotizave.com/v1/fx/route?${params}`, {
  headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY }
})
const data = await res.json()
// data.best.market → mercado óptimo
import os, requests

r = requests.get(
    'https://api.cotizave.com/v1/fx/route',
    params={'from': 'USD', 'to': 'VES', 'amount': 1000, 'direction': 'send'},
    headers={'X-API-Key': os.environ['COTIZAVE_API_KEY']}
)
data = r.json()
# data['best']['market'] → mercado óptimo

Mejor mercado para comprar USD pagando VES (con cotizaciones frescas, max 30 min):

curl "https://api.cotizave.com/v1/fx/route?from=VES&to=USD&amount=500000&direction=receive&max_staleness=1800" \
  -H "X-API-Key: $COTIZAVE_API_KEY"

Response

200 OK

{
  "from": {
    "currency": "USD",
    "amount": 1000
  },
  "direction": "send",
  "best": {
    "market": "mexc",
    "type": "p2p",
    "rate": 649.02,
    "amount": 649020.00,
    "updated_at": "2026-04-08T17:28:00Z",
    "staleness_sec": 87
  },
  "alternatives": [
    {
      "market": "bybit",
      "type": "p2p",
      "rate": 638.50,
      "amount": 638500.00,
      "updated_at": "2026-04-08T17:29:00Z",
      "staleness_sec": 15
    },
    {
      "market": "binance",
      "type": "p2p",
      "rate": 637.87,
      "amount": 637870.00,
      "updated_at": "2026-04-08T17:29:00Z",
      "staleness_sec": 15
    },
    {
      "market": "parallel",
      "type": "parallel",
      "rate": 638.87,
      "amount": 638870.00,
      "updated_at": "2026-04-08T17:25:00Z",
      "staleness_sec": 255
    }
  ],
  "skipped": [
    {
      "market": "reference",
      "reason": "no_quote"
    }
  ],
  "fetched_at": "2026-04-08T17:29:15Z"
}

Schema de respuesta

CampoTipoDescripción
from.currencystringMoneda origen
from.amountnumberMonto de entrada
directionstringsend o receive (eco del parámetro)
bestRouteOptionEl mercado óptimo para la dirección pedida
alternativesRouteOption[]Otros mercados elegibles, ordenados de mejor a peor
skippedSkippedMarket[] | omitidoMercados descartados y motivo (omitido si vacío)
fetched_atstring (ISO 8601)Cuándo Cotizave armó la respuesta

Schema de RouteOption

CampoTipoDescripción
marketstringIdentificador del mercado
typestringreference, parallel o p2p
ratenumberTasa mid (VES por USD) aplicada
amountnumberMonto resultante en moneda destino usando este mercado
updated_atstring (ISO 8601)Cuándo se actualizó la cotización del mercado
staleness_secintegerAntigüedad de la cotización en segundos al momento de la llamada

Schema de SkippedMarket

CampoTipoDescripción
marketstringIdentificador del mercado descartado
reasonstringno_quote: mid ≤ 0 (fuente sin cotización válida). stale: cotización más vieja que max_staleness.

Cómo funciona direction

El parámetro direction define la perspectiva del ordenamiento:

  • send (default): el caller tiene USD y quiere maximizar los VES que recibe. Los mercados se ordenan por mid descendente. El mercado con la tasa más alta (más VES por dólar) es el mejor.
  • receive: el caller tiene VES y quiere comprar USD pagando lo menos posible. Los mercados se ordenan por mid ascendente. El mercado con la tasa más baja (menos VES por dólar) es el mejor.

Casos de uso típicos

"¿Dónde conviene cambiar hoy?"

Muéstrale al usuario el mejor exchange ordenado por tasa con una sola llamada:

const res = await fetch(
  'https://api.cotizave.com/v1/fx/route?from=USD&to=VES&amount=1000&direction=send',
  { headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY } }
)
const data = await res.json()
console.log(`Mejor: ${data.best.market} — ${data.best.rate} Bs/USD`)
data.alternatives.slice(0, 3).forEach(alt => {
  console.log(`  ${alt.market}: ${alt.rate} Bs/USD`)
})

Arbitraje automatizado

Identifica la mejor compra y la mejor venta entre mercados para calcular el margen de arbitraje:

const [send, receive] = await Promise.all([
  fetch('https://api.cotizave.com/v1/fx/route?from=USD&to=VES&amount=1000&direction=send', {
    headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY }
  }).then(r => r.json()),
  fetch('https://api.cotizave.com/v1/fx/route?from=VES&to=USD&amount=1000&direction=receive', {
    headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY }
  }).then(r => r.json())
])
console.log(`Mejor para vender USD: ${send.best.market} (${send.best.rate})`)
console.log(`Mejor para comprar USD: ${receive.best.market} (${receive.best.rate})`)

Widget de tasa óptima

Muestra el mercado top destacado junto con las alternativas ordenadas:

const res = await fetch(
  `https://api.cotizave.com/v1/fx/route?from=USD&to=VES&amount=${amount}&direction=send`,
  { headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY } }
)
const { best, alternatives } = await res.json()
// Renderiza best con badge "Mejor tasa"
// Renderiza alternatives como lista secundaria

Errores posibles

Códigoerror.codeCausa
400missing_fieldFalta amount
400invalid_formatamount no es un número, o max_staleness no es un entero
401invalid_api_keyAPI Key inválida, faltante o revocada
402feature_not_in_planTu plan no incluye /v1/fx/route. Body: {"code":"feature_not_in_plan","message":"...","feature":"route","current_plan":"indie"}
429rate_limit_exceededCuota mensual agotada
500internal_errorError inesperado del lado de Cotizave

Shape del error 402

Cuando el plan no incluye este endpoint, el body incluye campos adicionales para facilitar el upgrade:

{
  "code": "feature_not_in_plan",
  "message": "This endpoint requires a Pro plan or higher.",
  "feature": "route",
  "current_plan": "indie"
}

Notas importantes

Disponibilidad desde Pro

/v1/fx/route es exclusivo de los planes Pro y Enterprise. Los planes Free, Starter e Indie pueden calcular el mejor mercado manualmente usando /v1/fx/rates + cálculo del lado del cliente, pero /route centraliza esa lógica, agrega filtrado por frescura y devuelve el array de alternativas ya ordenado.

Cuota: 1 unidad por llamada

Aunque consulta 9 mercados internamente, /v1/fx/route cuenta como 1 unidad de tu cuota mensual (el snapshot ya está cacheado en Redis).