MetalAPI
XAU3997,89−1,54 %XAG53,936−1,51 %XPT1554,47−0,83 %XPD1047,03−0,44 %XCU6,5080+2,29 %WTI103,27+3,82 %BRENT111,70−1,30 %EUR1,120400−0,01 %GBP1,337500−0,01 %JPY0,0063761+0,14 %CHF1,213445−0,25 %TRY0,020125−0,12 %BTC80.329,75−0,55 %ETH2329,36−1,13 %
Todos los artículos
OroAPITutorial

API de precios del oro: la guía completa para desarrolladores

Cómo usar una API de precios del oro: obtén una clave, llámala desde curl, JavaScript y Python, lee bien las cotizaciones y gestiona historial, errores, cuotas y caché.

Por MetalAPI Team··9 min de lectura

Qué te ofrece una API de precios del oro

Una API de precios del oro devuelve el precio actual e histórico del oro como datos estructurados, normalmente JSON sobre HTTPS, para que tu software pueda usarlo sin extraer datos de páginas web ni copiar cifras a mano. En MetalAPI, el oro tiene el símbolo XAU, el código ISO 4217 de una onza troy de oro. Su precio en tiempo real es el precio al contado: el punto medio entre las cotizaciones interbancarias de compra (bid) y de venta (ask).

La mayoría de las integraciones no son sistemas de trading. Los usos típicos son estos:

  • Tiendas online y joyerías que actualizan el precio de sus productos de oro según se mueve el mercado.
  • Calculadoras de oro para fundir, joyería por quilates o primas de lingotes.
  • Aplicaciones de seguimiento de carteras y de finanzas personales que valoran tenencias en una divisa local.
  • Sistemas contables y ERP que revalorizan el inventario a un precio de cierre diario.
  • Paneles, boletines e informes internos que necesitan un gráfico del último año.

La misma API cubre la plata (XAG), el platino (XPT) y el paladio (XPD), cuatro metales industriales, cinco contratos de energía, 57 divisas y 13 criptomonedas: 83 símbolos en total, todos ellos en la página de símbolos. Esta guía se centra en el oro, pero todo lo que contiene se aplica también a los demás símbolos.

Obtén una clave API

Crea una cuenta gratuita. El plan Free no requiere tarjeta de crédito e incluye 100 solicitudes al mes con actualización diaria de precios, suficiente para crear y probar una integración. Los planes de pago añaden precios más recientes, más solicitudes y endpoints adicionales; la tabla de planes de más abajo los resume.

En el panel, abre API keys y crea una clave. Las claves empiezan por mk_live_. La clave completa solo se muestra una vez, porque solo se almacena un hash de ella, así que guárdala de inmediato en una variable de entorno o en un gestor de secretos:

Shell
export METALAPI_KEY="mk_live_your_key_here"

La API acepta la clave de tres formas equivalentes: un parámetro de consulta api_key, una cabecera Authorization: Bearer o una cabecera X-API-Key. En producción, es preferible usar una cabecera, porque las URL completas suelen acabar en registros de acceso, proxies y herramientas de seguimiento de errores. La guía de autenticación también explica las claves restringidas por dominio para llamadas desde el navegador.

Tres formas de autenticarse
# 1. Parámetro de consulta
curl "https://metalapi.com/api/v1/latest?api_key=$METALAPI_KEY&currencies=XAU"

# 2. Cabecera Authorization
curl "https://metalapi.com/api/v1/latest?currencies=XAU" \
  -H "Authorization: Bearer $METALAPI_KEY"

# 3. Cabecera X-API-Key
curl "https://metalapi.com/api/v1/latest?currencies=XAU" \
  -H "X-API-Key: $METALAPI_KEY"

Tu primera solicitud con curl, JavaScript y Python

Cada endpoint es una simple solicitud GET bajo https://metalapi.com/api/v1/. El endpoint /latest devuelve los precios actuales. base establece la divisa en la que se expresan los precios (por defecto, USD) y currencies limita la respuesta a los símbolos que necesitas. Una solicitud puede devolver muchos símbolos y aun así cuenta como una sola solicitud.

curl
curl "https://metalapi.com/api/v1/latest?base=USD&currencies=XAU,XAG" \
  -H "X-API-Key: $METALAPI_KEY"

Una respuesta correcta tiene este aspecto. Las cifras son los valores de ejemplo que se usan en toda la documentación de MetalAPI, no precios en tiempo real:

Respuesta de ejemplo
{
  "success": true,
  "timestamp": 1792834892,
  "date": "2026-10-24",
  "base": "USD",
  "rates": {
    "XAU": 0.0002501319,
    "USDXAU": 3997.89,
    "XAG": 0.0185392857,
    "USDXAG": 53.94
  },
  "rate_limit": {
    "limit": 10000,
    "remaining": 9876,
    "reset": 1793491200,
    "used": 124,
    "plan": "Standard",
    "reset_date": "2026-11-01T00:00:00.000Z"
  }
}

La misma llamada desde Node.js 18 o posterior, que incluye fetch de serie. Guárdala como gold.mjs para que funcione el await de nivel superior y ejecuta node gold.mjs:

gold.mjs
const params = new URLSearchParams({ base: "USD", currencies: "XAU,XAG" });
const res = await fetch(`https://metalapi.com/api/v1/latest?${params}`, {
  headers: { Authorization: `Bearer ${process.env.METALAPI_KEY}` },
  signal: AbortSignal.timeout(10_000),
});
const data = await res.json();

if (!data.success) {
  throw new Error(`MetalAPI ${data.error.code} (${data.error.type}): ${data.error.info}`);
}

const gold = data.rates[`${data.base}XAU`];
const asOf = new Date(data.timestamp * 1000).toISOString();
console.log(`Gold: ${gold} ${data.base} per troy ounce (data from ${asOf})`);

Y desde Python con la biblioteca requests:

gold.py
import os

import requests

resp = requests.get(
    "https://metalapi.com/api/v1/latest",
    params={"base": "USD", "currencies": "XAU,XAG"},
    headers={"X-API-Key": os.environ["METALAPI_KEY"]},
    timeout=10,
)
data = resp.json()
if not data["success"]:
    err = data["error"]
    raise RuntimeError(f"MetalAPI {err['code']} ({err['type']}): {err['info']}")

base = data["base"]
print(f"Gold:   {data['rates'][base + 'XAU']} {base} per troy ounce")
print(f"Silver: {data['rates'][base + 'XAG']} {base} per troy ounce")

Ambos fragmentos construyen la clave de la cotización a partir de data.base en lugar de escribirla a mano. Esa pequeña costumbre mantiene el código correcto cuando más adelante cambias la divisa base, y nos lleva a la parte más importante de esta guía.

Interpreta correctamente el formato de las cotizaciones

Cada símbolo aparece dos veces en rates, y las dos cifras son inversas entre sí:

ClaveSignificadoValor de ejemplo
USDXAUPrecio de una onza troy de oro en la divisa base (USD)3997.89
XAUOnzas troy de oro que se compran con una unidad de la divisa base0.0002501319

La regla general: rates.<BASE><SYMBOL> es el precio de una unidad del símbolo en la divisa base. La clave simple rates.<SYMBOL> es la inversa: unidades del símbolo por cada unidad de la base. La forma inversa se mantiene por compatibilidad con las API de estilo forex y con las integraciones antiguas de MetalAPI.

El error más común en las integraciones de precios del oro es leer rates.XAU y tratarlo como el precio. Es 1 ÷ precio, así que una ficha de producto muestra 0,00025 en lugar de 3997,89, y cualquier cálculo que multiplique por ese valor se equivoca en muchos órdenes de magnitud. Lee la clave con prefijo, como rates.USDXAU o rates.EURXAU.

Si ya guardas valores inversos de una integración antigua, no tienes que volver a descargarlos: precio = 1 ÷ inverso. Con el ejemplo anterior, 1 ÷ 0,0002501319 vuelve a dar 3997,89, salvo por las últimas cifras del redondeo.

Las divisas siguen la misma regla. Con base USD, USDEUR es el precio de un euro en dólares y EUR es la cantidad de euros por dólar. La guía de formatos de datos tiene más ejemplos, incluidas las claves bid y ask disponibles en el plan Standard y superiores.

Divisas base y unidades

Para obtener el precio del oro en otra divisa, cambia base. La clave de la cotización cambia con ella: base=EUR devuelve EURXAU, y base=INR devuelve INRXAU. Las cotizaciones cruzadas proceden de una misma instantánea, así que el oro en euros y el euro en dólares siempre son coherentes entre sí.

Los precios de los metales son por onza troy de forma predeterminada. El parámetro unit los devuelve por otra unidad de peso:

unitPrecio porUso habitual
troy_oz (por defecto)Onza troy, 31,1034768 gCotizaciones de lingotes
gramGramoJoyería y venta al público
kilogramKilogramoLingotes de un kilo, mercado mayorista
ounceOnza avoirdupois, 28,349523125 gRara vez adecuada para el oro
poundLibra avoirdupoisCobre
metric_tonTonelada métrica (1000 kg)Aluminio, zinc
short_tonTonelada corta (2000 lb)Acero (HRC)

Esta solicitud devuelve el oro y la plata en euros por gramo. Cuando unit no es el valor por defecto, la respuesta lo repite en un campo unit de nivel superior:

bash
curl "https://metalapi.com/api/v1/latest?base=EUR&currencies=XAU,XAG&unit=gram" \
  -H "X-API-Key: $METALAPI_KEY"

unit=ounce (y su forma abreviada oz) es la onza avoirdupois, aproximadamente un 8,9 % más ligera que una onza troy. Para precios de lingotes, omite unit o pasa troy_oz.

unit solo afecta a los metales preciosos e industriales. La energía, las divisas y las criptomonedas no cambian. Para conocer los detalles sobre onzas troy, gramos, tolas y redondeo, lee Onzas troy, gramos y kilogramos. Si vendes joyería, Precios del oro por quilate explica los precios de 22K y 18K y el endpoint /carat.

Precios históricos del oro

Los precios pasados usan los mismos parámetros y el mismo formato de respuesta. El historial empieza en 2000 para los metales y la energía, el 4 de enero de 1999 para las divisas y en 2014 para las criptomonedas. Cuatro endpoints cubren la mayoría de las necesidades:

  • /YYYY-MM-DD (o /historical?date=YYYY-MM-DD, o /yesterday): precios de cierre de un día. Para los fines de semana y festivos, se devuelve el cierre del día de negociación más reciente.
  • /timeframe (alias /timeseries): cierres diarios entre start_date y end_date, hasta 30 días por solicitud en Free y 365 días en los planes de pago.
  • /change: cotización inicial, cotización final, variación absoluta y variación porcentual entre dos fechas.
  • /ohlc: apertura, máximo, mínimo y cierre de un día.
bash
# Oro y plata al cierre del 15 de enero de 2024
curl "https://metalapi.com/api/v1/2024-01-15?currencies=XAU,XAG" \
  -H "X-API-Key: $METALAPI_KEY"

# Cierres diarios del oro en euros de septiembre de 2026
curl "https://metalapi.com/api/v1/timeframe?start_date=2026-09-01&end_date=2026-09-30&base=EUR&currencies=XAU" \
  -H "X-API-Key: $METALAPI_KEY"

Los precios de cierre de los días pasados no cambian, así que guárdalos una vez en lugar de volver a pedirlos. Precios históricos del oro y la plata por API explica paso a paso cómo paginar 25 años de datos, guardarlos localmente y representarlos en gráficos. La guía de datos históricos incluye una función auxiliar en JavaScript para rangos largos.

Errores, cuotas y límites de los planes

Una solicitud fallida devuelve un código de estado HTTP de error y un cuerpo con success: false. El objeto error tiene un code numérico, un type legible por máquinas y un info legible por personas. Decide qué hacer según code o type, nunca según el texto de info. Los errores de límite por minuto (104), cuota (105), restricción del plan (106) y periodo (207) también incluyen una upgrade_url:

Error de ejemplo
{
  "success": false,
  "error": {
    "code": 106,
    "type": "plan_restriction",
    "info": "The carat endpoint requires a paid subscription plan",
    "upgrade_url": "https://metalapi.com/dashboard/billing"
  }
}

Los códigos que es más probable que encuentres:

CódigoTipoHTTPQué hacer
101, 102no_api_key, invalid_api_key401Envía una clave válida y revisa tu variable de entorno
104too_many_requests429Espera los segundos de Retry-After y vuelve a intentarlo
105quota_exceeded429Cuota mensual agotada; se restablece el día 1 (UTC)
106plan_restriction403Endpoint o parámetro no incluido en tu plan
205invalid_date400Corrige una fecha mal formada o futura
207timeframe_too_long400Divide el rango en solicitudes más cortas
300no_results404Sin datos, por ejemplo antes del inicio del historial
500, 503server_error, service_unavailable500, 503Reintenta con espera exponencial

Cada respuesta autenticada informa de tu cuota, tanto en las cabeceras X-RateLimit-* como en el objeto rate_limit del cuerpo. /usage y /symbols nunca cuentan para la cuota, así que tu sistema de monitorización puede llamarlos libremente. Las solicitudes rechazadas con 104, 106, 107 o con un error del servidor no se facturan, pero los errores de validación sí. La guía de manejo de errores enumera todos los códigos e incluye una función auxiliar de reintentos.

Los planes se diferencian sobre todo en el volumen de solicitudes y en lo recientes que son los precios:

PlanPrecio / mesSolicitudes / mesActualizacionesAñade
Free0 USD100DiariasRangos de 30 días
Lite4,99 USD100030 minPrecios por quilate, rangos de 365 días
Standard11,99 USD10.00010 minPrecios bid/ask
Advanced24,99 USD50.0001 minAlertas por webhook
Pro49,99 USD100.0001 minStream en tiempo real
Ultra99,99 USD500.00015 sMayor volumen
Business149,99 USD500.00015 sSLA de disponibilidad
Enterprise299,99 USD1.500.0005 sMáximo volumen

La facturación anual ahorra hasta un 25 %. La página de precios siempre tiene los detalles actualizados.

Caché y consejos para producción

Solicitar /latest con más frecuencia de la que se actualiza tu plan devuelve las mismas cifras y gasta cuota para nada. Guarda en caché los últimos precios durante al menos el intervalo de actualización de tu plan, y guarda los días pasados de forma permanente. Esta función auxiliar en Python guarda en caché los últimos precios y sigue sirviendo la última respuesta válida si no se puede contactar con la API:

cache.py
import os
import time

import requests

TTL_SECONDS = 600  # Plan Standard: los precios se actualizan cada 10 minutos
session = requests.Session()
session.headers["X-API-Key"] = os.environ["METALAPI_KEY"]
_cache = {"at": 0.0, "data": None}


def latest_prices():
    now = time.monotonic()
    if _cache["data"] and now - _cache["at"] < TTL_SECONDS:
        return _cache["data"]
    try:
        r = session.get(
            "https://metalapi.com/api/v1/latest",
            params={"currencies": "XAU,XAG,XPT,XPD"},
            timeout=10,
        )
        data = r.json()
    except (requests.RequestException, ValueError):
        data = None
    if data and data.get("success"):
        _cache.update(at=now, data=data)
        return data
    if _cache["data"]:
        return _cache["data"]  # últimos precios válidos; muestra su marca de tiempo
    raise RuntimeError(data["error"] if data else "MetalAPI unreachable")

Algunas costumbres más que mantienen una integración barata y fiable:

  • Pide todos los símbolos en una sola llamada. currencies=XAU,XAG,XPT,XPD cuesta una solicitud; cuatro llamadas separadas cuestan cuatro.
  • Mantén la clave en el servidor. Si un navegador tiene que llamar a la API, usa una clave restringida por dominio. Para mostrar precios en un sitio web sin escribir código, un widget integrable mantiene la clave completamente fuera de la página.
  • Muestra la marca de tiempo. timestamp es la hora de los datos, no la de tu solicitud. Muéstrala junto al precio, sobre todo cuando sirves un valor en caché o el mercado está cerrado por el fin de semana.
  • Presupuesta tus consultas. Consultar cada 10 minutos consume unas 4500 solicitudes al mes, y consultar cada minuto, unas 45.000. Desde el plan Pro puedes usar el stream en tiempo real en su lugar, y desde Advanced puedes recibir alertas de precio por webhook.
  • Usa tiempos de espera y reintentos selectivos. Establece un tiempo de espera de unos 10 segundos, reintenta 104 después de Retry-After y los errores 5xx con espera exponencial, y nunca reintentes los errores de validación.
  • Valida los símbolos de antemano. Carga /symbols una vez al arrancar (es gratuito) y rechaza los códigos desconocidos antes de que te cuesten una solicitud.

Si trabajas con asistentes de IA, el servidor MCP de MetalAPI en https://metalapi.com/mcp expone los mismos datos como herramientas, para que Claude, ChatGPT, Cursor o VS Code puedan consultar precios e historial del oro con tu plan; consulta IA y MCP. Para cada endpoint y parámetro, la referencia es la documentación de la API.

Pruébalo con tus propios datos

Crea una cuenta gratuita y haz tu primera solicitud en menos de dos minutos. 100 solicitudes al mes, sin tarjeta de crédito.

Sigue leyendo