Para obtener precios del oro en tiempo real en PHP, envía un GET a api.goldprice.dev/v1/spot/XAU-USD-SPOT con tu clave en la cabecera X-API-Key. Usa cURL nativo, sin Composer.
Decodifica el JSON, conserva los precios como cadenas y calcula con BCMath. Guarda cada símbolo en caché durante 60 segundos. El plan gratuito incluye 5.000 consultas/mes, sin tarjeta. Probado en junio de 2026 con PHP 8.3.
Obtén tu clave de API de goldprice.dev
Crea una cuenta gratuita en goldprice.dev/onboarding. Tras confirmar tu correo, verás en tu panel una clave que empieza por ga_live_. Guárdala como variable de entorno:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_hereEl plan gratuito incluye 5.000 consultas/mes y precios al contado del oro en 31 monedas. No necesitas tarjeta.
Comprueba las extensiones necesarias
No necesitas paquetes de Composer. PHP 8 incluye curl y json; bcmath es una extensión estándar para cálculos decimales exactos. Comprueba que las tres estén activadas:
php -m | grep -E '^(curl|json|bcmath)$'# curl# json# bcmath <- if missing, install php8.3-bcmath (or enable in php.ini)Escribe el cliente de goldprice
Guarda este código como goldprice.php. spot() almacena cada símbolo durante 60 segundos en un array estático, reintenta hasta 3 veces ante 429 con esperas exponenciales y devuelve el array decodificado. Los precios siguen siendo cadenas para que BCMath pueda calcular con precisión.
<?php// php: goldprice.php, native cURL + BCMath, no Composer// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTdeclare(strict_types=1);const API_BASE = 'https://api.goldprice.dev';const TIMEOUT = 5; // secondsconst TTL = 60; // secondsfinal class RateLimitedException extends RuntimeException {}final class GoldpriceClient{ private string $apiKey; /** @var array<string, array{data: array, expires: int}> */ private static array $cache = []; public function __construct() { $key = getenv('GOLDPRICE_API_KEY'); if ($key === false || $key === '') { throw new RuntimeException('GOLDPRICE_API_KEY not set'); } $this->apiKey = $key; } /** * Fetch live spot price. Cached 60s per symbol, retries 3x on 429. * Prices stay as strings for BCMath. */ public function spot(string $symbol = 'XAU-USD-SPOT'): array { $now = time(); if (isset(self::$cache[$symbol]) && self::$cache[$symbol]['expires'] > $now) { return self::$cache[$symbol]['data']; } for ($attempt = 0; $attempt < 3; $attempt++) { try { $data = $this->fetch($symbol); self::$cache[$symbol] = ['data' => $data, 'expires' => $now + TTL]; return $data; } catch (RateLimitedException) { sleep(1 << $attempt); // 1s, 2s, 4s } } throw new RateLimitedException('goldprice: 429 after 3 retries'); } private function fetch(string $symbol): array { $ch = curl_init(API_BASE . '/v1/spot/' . rawurlencode($symbol)); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => TIMEOUT, CURLOPT_HTTPHEADER => ['X-API-Key: ' . $this->apiKey], ]); $body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($code === 429) { throw new RateLimitedException('rate limited'); } if ($code !== 200 || $body === false) { throw new RuntimeException("goldprice: unexpected status {$code}"); } return json_decode((string) $body, true, 512, JSON_THROW_ON_ERROR); }}$client = new GoldpriceClient();$r = $client->spot('XAU-USD-SPOT');// Prices are strings; use BCMath for exact math (e.g. price for 5 oz):$fiveOz = bcmul($r['price'], '5', 4);printf("%s-%s: %s (computed %s)\n", $r['symbol'], $r['quote_currency'], $r['price'], $r['computed_at']);printf("5 troy oz = %s %s\n", $fiveOz, $r['quote_currency']);Ejecútalo
Ejecuta el archivo desde la CLI en la terminal donde exportaste GOLDPRICE_API_KEY. La primera llamada consulta la API; las siguientes llamadas a spot() en el mismo proceso durante 60 segundos devuelven el array en caché. La caché estática pertenece al proceso. Usa APCu o Redis para compartirla entre solicitudes de PHP-FPM.
php goldprice.php# XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)# 5 troy oz = 20063.7500 USDCambia de moneda o metal
Los símbolos siguen el formato METAL-CURRENCY-SPOT. Pasa a spot() cualquiera de las 31 monedas al contado. Cada símbolo tiene su propia caché en el array estático. Una página con 5 símbolos hace como máximo 5 llamadas sin caché y las reutiliza si vuelve a renderizarse dentro del intervalo.
$client = new GoldpriceClient();// USD spot, default$client->spot('XAU-USD-SPOT');$client->spot('XAU-INR-SPOT');$client->spot('XAU-EUR-SPOT');// Silver in USD$client->spot('XAG-USD-SPOT');Resultado esperado
{ "symbol": "XAU", "quote_currency": "USD", "unit": "troy_ounce", "contract_type": "spot", "price": "4012.75", "is_stale": false, "computed_at": "2026-10-23T07:00:18.221118+00:00"}La CLI imprime dos líneas: símbolo, moneda, precio y fecha y hora; después, el producto calculado con BCMath para 5 onzas troy. Tu código utiliza el array decodificado, con los precios como cadenas.
Errores comunes
| Código | Qué ves | Solución |
|---|---|---|
| 401 | RuntimeException: goldprice: unexpected status 401 | Falta la clave de API o no es válida. Comprueba que PHP recibe la variable: php -r 'echo getenv("GOLDPRICE_API_KEY");'. PHP-FPM no comparte las variables de la CLI. Configura la clave con fastcgi_param o tu gestor de procesos. Si está vacía, cópiala de nuevo desde tu panel. |
| 429 | Los tres reintentos con esperas devuelven 429 y se lanza RateLimitedException | Has alcanzado el límite por minuto. La caché de 60 segundos lo evita con tráfico regular. En PHP-FPM, la caché estática pertenece a cada solicitud. Usa APCu (apcu_fetch / apcu_store) para compartirla entre solicitudes. Para un volumen elevado y continuo, consulta los planes de pago en /pricing. |
| N/A | Errores de redondeo al convertir los precios a float para calcular | No conviertas el precio a (float) antes de calcular: los números en coma flotante de PHP pierden precisión al sumar. Conserva la cadena de la API y usa bcadd, bcmul y bccomp con una escala explícita. Activa la extensión bcmath si esas funciones no están definidas. |
Más opciones
- Usa
apcu_store/apcu_fetchpara compartir la caché estática y atender a los procesos PHP-FPM con una consulta durante los 60 segundos - Añade un método
bars()para/v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...y representa los datos con tu motor de plantillas - Encapsula
spot()en un servicio sencillo de Laravel o Symfony y regístralo en el contenedor para inyectar dependencias - Añade una comprobación
If-None-Match/ ETag si varios procesos consultan el mismo símbolo, para evitar respuestas con datos sin cambios - Usa
bcdivcon el factor de conversión de onzas troy a gramos para mostrar precios por gramo al público