← Volver a docs
Pro+POST

POST /v1/fx/bulk/convert

Convierte hasta 50 montos en una sola llamada usando el mismo mercado para todos. La API hace un único lookup de tasa y aplica las multiplicaciones de forma trivial.

Cuenta como 1 unidad de tu cuota mensual, independientemente de cuántos montos incluyas. Si necesitas convertir listas de precios, facturas o montos de una tabla, este endpoint es más eficiente que llamar/v1/fx/convert en loop.

Disponible únicamente en el plan Pro y superiores. Tiene un cap adicional de 300 llamadas por hora implementado vía script Redis Lua, independiente de la cuota mensual.


Request

POST /v1/fx/bulk/convert HTTP/1.1
Host: api.cotizave.com
X-API-Key: ctz_live_aB3cD8fG2hJ5kL9mN1pQ4rS7tU0vWxYzA6bC3d
Content-Type: application/json

{
  "from": "USD",
  "to": "VES",
  "amounts": [100, 250, 500, 1000],
  "market": "parallel"
}

Body (JSON)

CampoTipoRequeridoDefaultDescripción
fromstringMoneda origen: USD o VES
tostringMoneda destino: VES o USD. Debe diferir de from.
amountsnumber[]Lista de montos a convertir. Mínimo 1, máximo 50.
marketstringNoreferenceMercado a usar: reference, parallel, binance, bybit, okx, bitget, mexc

Ejemplo con curl

curl -X POST "https://api.cotizave.com/v1/fx/bulk/convert" \
  -H "X-API-Key: $COTIZAVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"from":"USD","to":"VES","amount":100},{"from":"USD","to":"VES","amount":250}],"via":"reference"}'
const res = await fetch('https://api.cotizave.com/v1/fx/bulk/convert', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COTIZAVE_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    items: [
      { from: 'USD', to: 'VES', amount: 100 },
      { from: 'USD', to: 'VES', amount: 250 }
    ],
    via: 'reference'
  })
})
const data = await res.json()
import os, requests

r = requests.post(
    'https://api.cotizave.com/v1/fx/bulk/convert',
    headers={'X-API-Key': os.environ['COTIZAVE_API_KEY']},
    json={
        'items': [
            {'from': 'USD', 'to': 'VES', 'amount': 100},
            {'from': 'USD', 'to': 'VES', 'amount': 250},
        ],
        'via': 'reference'
    }
)
data = r.json()

Response

200 OK

{
  "rate": 638.87,
  "market": "parallel",
  "type": "parallel",
  "updated_at": "2026-04-08T17:25:00Z",
  "results": [
    { "amount": 100,  "result": 63887.00  },
    { "amount": 250,  "result": 159717.50 },
    { "amount": 500,  "result": 319435.00 },
    { "amount": 1000, "result": 638870.00 }
  ],
  "total_in": 1850,
  "total_out": 1182009.50
}

Headers de respuesta

HeaderValor de ejemploDescripción
X-RateLimit-Cost1Unidades de cuota descontadas por esta llamada (siempre 1)
X-Bulk-Operations4Cantidad de montos procesados en la llamada

Schema de respuesta

CampoTipoDescripción
ratenumberTasa mid aplicada a todos los montos
marketstringIdentificador del mercado usado
typestringTipo de tasa: reference, parallel o p2p
updated_atstring (ISO 8601)Cuándo se actualizó la tasa del mercado
resultsarrayResultados individuales en el mismo orden que amounts
results[].amountnumberMonto de entrada (eco del array amounts)
results[].resultnumberMonto convertido para ese elemento
total_innumberSuma de todos los montos de entrada
total_outnumberSuma de todos los montos convertidos

Casos de uso típicos

Nómina en bolívares

Convierte un array de salarios en USD a VES de una sola llamada:

const salaries = employees.map(e => ({ from: 'USD', to: 'VES', amount: e.salaryUSD }))

const res = await fetch('https://api.cotizave.com/v1/fx/bulk/convert', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COTIZAVE_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ items: salaries, via: 'reference' })
})

const { results } = await res.json()
// results[i].result → salario en VES para employees[i]

Catálogo de precios

Convierte un lote de precios de productos en USD a VES en una sola llamada:

const items = products.map(p => ({ from: 'USD', to: 'VES', amount: p.priceUSD }))

const res = await fetch('https://api.cotizave.com/v1/fx/bulk/convert', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({ items, via: 'reference' })
})

const { rate, results } = await res.json()
console.log(`Tasa BCV aplicada: ${rate} Bs/USD`)
// results[i].result → precio en VES para products[i]

Reportes de divisas

Convierte una lista de montos de facturas en USD para reportes contables:

// Agrupa las facturas del mes y convierte en una sola llamada
const items = invoices.map(inv => ({ from: 'USD', to: 'VES', amount: inv.amountUSD }))

const res = await fetch('https://api.cotizave.com/v1/fx/bulk/convert', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.COTIZAVE_API_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({ items, via: 'reference' })  // BCV para efectos contables
})

const data = await res.json()
console.log(`Total USD: ${data.total_in} — Total VES: ${data.total_out}`)
// Asocia results[i] con invoices[i]

Errores posibles

Códigoerror.codeCausa
400invalid_formatJSON inválido, amounts supera 50 elementos, o montos no son números
401invalid_api_keyAPI Key inválida, faltante o revocada
402feature_not_in_planTu plan no incluye bulk convert. Body: {"code":"feature_not_in_plan","message":"...","feature":"bulk_convert","current_plan":"indie"}
429rate_limit_exceededCuota mensual agotada, o se superaron las 300 llamadas/hora del cap bulk
500internal_errorError inesperado del lado de Cotizave

Shape del error 400 cuando se supera el límite de 50

{
  "code": "invalid_format",
  "message": "Max 50 amounts per request.",
  "field": "amounts",
  "max": 50,
  "got": 73
}

Shape del error 402

{
  "code": "feature_not_in_plan",
  "message": "Bulk convert requires a Pro plan or higher.",
  "feature": "bulk_convert",
  "current_plan": "indie"
}

Notas importantes

Una tasa para todos los montos

El endpoint hace un solo lookup de tasa (desde el snapshot cacheado en Redis) y la aplica a todos los montos. Todos los results[i].result reflejan la misma tasa rate. Si necesitas tasas distintas por monto, usa /v1/fx/convert individualmente.

Cap de 300 llamadas por hora

Además de tu cuota mensual, este endpoint tiene un límite dedicado de 300 llamadas por hora, implementado vía script Lua atómico en Redis. Es una protección adicional frente a usos intensivos en ráfaga. Si superas este cap recibirás 429 rate_limit_exceeded hasta que la ventana de una hora se resetee.

Orden del array results

El array results respeta el mismo orden que el array amounts del request.results[i].amount es siempre un eco de amounts[i], por lo que puedes correlacionar los resultados con tus datos de origen por índice.