Getting started with Gold May 2027 (GCK27) - Per Troy Ounce Price API in PHP
You need to quote, hedge, or reprice against Gold May 2027 futures in real time, measured per troy ounce, and you want to do it from PHP. By the end of this guide you will query Metals-API for GCK27, read the USD per troy ounce price, handle units and timestamps correctly, cache responses, and print a production-ready price for downstream trading, pricing, or analytics workflows.
What you will build: a PHP cURL fetch for GCK27 (Gold May 2027) per troy ounce
We will use the Latest endpoint to request the GCK27 symbol and extract two fields:
- rates.GCK27 — ounces per 1 USD (inverse quote)
- rates.USDGCK27 — USD per 1 ounce (direct quote you likely want)
Because Metals-API uses USD as the base currency by default, the most convenient field for pricing per troy ounce is rates.USDGCK27. If it is not present on your plan, you can invert rates.GCK27 to compute USD per ounce.
Before you start: sign in and generate an API key. There is no free trial. You can create your account here: Register. For symbol availability, see the catalog: Symbols. Full endpoint details live here: Documentation.
Endpoint to call: Latest
The Latest endpoint provides the current snapshot for requested symbols. We’ll request GCK27 only, to reduce payload and parsing complexity.
cURL request (copy/paste)
curl -s "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&symbols=GCK27"
Official JSON response example for GCK27
This is a real Metals-API response for GCK27. Use it to validate your parser and unit handling:
{"success":true,"timestamp":1791245340,"date":"2026-10-06","base":"USD","rates":{"GCK27":0.00023562676720075,"USD":1,"USDGCK27":4244.000000000073}}
How to read this payload
- success: true — request succeeded.
- timestamp: 1791245340 — Unix epoch seconds (UTC). Convert to your timezone if you display local times.
- date: 2026-10-06 — UTC date for this snapshot.
- base: USD — all “rates.*” are relative to 1 USD unless the pair key explicitly encodes the inverse.
- rates.GCK27 = 0.00023562676720075 — ounces per 1 USD (inverse). Invert it if you need USD/oz: 1 / 0.00023562676720075 ≈ 4244.000000000073 USD per oz.
- rates.USDGCK27 = 4244.000000000073 — USD per 1 ounce (direct). Use this value for pricing per troy ounce.
For most applications, rates.USDGCK27 is the field to display and store as the per-ounce price of Gold May 2027 (GCK27).
PHP cURL: fetch, parse, and compute USD/oz for GCK27
This snippet calls the Latest endpoint, extracts USD per troy ounce, and falls back to an inversion if USDGCK27 is not present in your plan’s response.
<?php
// Configure
$apiKey = getenv('METALS_API_KEY') ?: 'YOUR_API_KEY';
$symbols = 'GCK27';
$url = "https://metals-api.com/api/latest?access_key=" . urlencode($apiKey) . "&symbols=" . urlencode($symbols);
// Basic caching: reuse the last response for 60 seconds to reduce calls
$cacheFile = sys_get_temp_dir() . '/metals-gck27-latest.json';
$cacheTtlSeconds = 60;
$useCache = false;
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTtlSeconds)) {
$json = file_get_contents($cacheFile);
$useCache = true;
} else {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true,
]);
$json = curl_exec($ch);
if ($json === false) {
http_response_code(502);
die("Error calling Metals-API: " . curl_error($ch) . PHP_EOL);
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status < 200 || $status >= 300) {
http_response_code(502);
die("Non-2xx status from Metals-API: " . $status . PHP_EOL . $json);
}
file_put_contents($cacheFile, $json);
}
$data = json_decode($json, true);
if (!is_array($data) || empty($data['success'])) {
http_response_code(502);
die("Invalid response payload.");
}
// Read fields
$ts = isset($data['timestamp']) ? (int)$data['timestamp'] : null;
$dateUtc = $data['date'] ?? null;
$rates = $data['rates'] ?? [];
$ozPerUsd = $rates['GCK27'] ?? null; // ounces per 1 USD (inverse)
$usdPerOz = $rates['USDGCK27'] ?? null; // USD per 1 ounce (direct)
// Compute fallback if needed
if ($usdPerOz === null && $ozPerUsd) {
$usdPerOz = 1.0 / $ozPerUsd;
}
if ($usdPerOz === null) {
http_response_code(502);
die("Missing both USDGCK27 and GCK27 rates.");
}
// Format output
$dt = $ts ? gmdate('Y-m-d H:i:s', $ts) . ' UTC' : ($dateUtc ? $dateUtc . ' 00:00:00 UTC' : 'unknown time');
// Units and conversions
$troyOunceToGram = 31.1034768;
$usdPerGram = $usdPerOz / $troyOunceToGram;
echo "Gold May 2027 (GCK27)\n";
echo "Price: " . number_format($usdPerOz, 2) . " USD per troy ounce\n";
echo " " . number_format($usdPerGram, 2) . " USD per gram\n";
echo "As of: " . $dt . ($useCache ? " (cached)" : "") . "\n";
JavaScript (Node.js) alternative
If you maintain build tooling or serverless functions in Node.js, here is an equivalent fetch and inversion fallback:
import fetch from 'node-fetch';
const API_KEY = process.env.METALS_API_KEY || 'YOUR_API_KEY';
const url = `https://metals-api.com/api/latest?access_key=${encodeURIComponent(API_KEY)}&symbols=GCK27`;
const TROY_OUNCE_TO_GRAM = 31.1034768;
const res = await fetch(url, { timeout: 10000 });
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
if (!data.success) {
throw new Error('API returned success=false');
}
const ozPerUsd = data?.rates?.GCK27; // ounces per 1 USD
let usdPerOz = data?.rates?.USDGCK27; // USD per 1 ounce
if (usdPerOz == null && ozPerUsd != null) {
usdPerOz = 1 / ozPerUsd;
}
if (usdPerOz == null) {
throw new Error('Missing USDGCK27 and GCK27');
}
const usdPerGram = usdPerOz / TROY_OUNCE_TO_GRAM;
console.log({
symbol: 'GCK27',
usdPerOz: Number(usdPerOz),
usdPerGram: Number(usdPerGram),
timestampUtc: data.timestamp ? new Date(data.timestamp * 1000).toISOString() : null
});
Units, base currency, and the GCK27 convention you must get right
- Base currency: USD. Unless otherwise specified, rates.* are relative to 1 USD. This is why rates.GCK27 is ounces per USD, not USD per ounce.
- Direct vs. inverse fields: When present, rates.USDGCK27 is already USD per ounce and requires no inversion. If it is absent, compute 1 / rates.GCK27.
- Troy ounces: Precious metals are quoted per troy ounce (31.1034768 grams). Always convert using troy, not avoirdupois ounces.
- Timestamps: timestamp is Unix seconds in UTC. Display as UTC or convert explicitly to your app’s timezone.
Caching and resilience for production
- Short-term cache: Keep a 30–60s cache to reduce latency and request volume. The example above uses a 60s file cache.
- Weekend/holiday handling: Futures and spot sessions have closures. If the timestamp does not advance, you may be seeing the last official update; continue serving the cached price and annotate “as of” time.
- Fallback logic: Prefer rates.USDGCK27, then invert rates.GCK27. If neither is present, surface a clear error and optionally degrade to your last good value.
- Precision: Use decimal types when available. For display, round to 2 decimals (USD) but keep full precision in storage.
- Key management: Store your Metals-API key in environment variables or a secrets manager, not in source control.
Expanding beyond the snapshot: historical and intraday context
For backfilling charts, calculating returns, and alerting on moves, you will typically combine the Latest snapshot with historical queries. While this article focuses on the Latest endpoint and GCK27, you can:
- Request a date-specific Historical snapshot to compare against previous closes.
- Use the Time-series endpoint to pull a daily series between two dates and compute returns or drawdowns.
Stay within the Metals-API contract for request formats and available parameters. Refer to the endpoint specifics in the Documentation. Confirm symbol availability and categories in the Symbols directory.
Practical pricing patterns for GCK27
- Convert to other units: USD/gram = USD/oz ÷ 31.1034768. For kilograms, multiply grams by 1000.
- Quote hedges: If your ERP or OMS prices finished goods per gram, compute usdPerGram and apply your spread or fees at the display layer.
- Risk controls: Store both the raw API rate and your derived USD/oz number to enable reconciliation and audit trails.
- Alerting: Poll Latest at your plan’s cadence; if abs(new - old) / old exceeds your threshold, emit an alert with the timestamp and symbol.
Gold and digital transformation: why GCK27 data belongs in your stack
Gold’s role in risk transfer is centuries old; what’s changed is the integration surface. Exposing GCK27 via an API means:
- You can stream live contract-aligned pricing into trading frontends and automated hedging tools.
- Data scientists can feature-engineer spreads between futures maturities, build roll curves, and test carry strategies directly from normalized JSON.
- Product teams can reprice jewelry SKUs, update margin dashboards, and offer customer quotes that reference a specific delivery month.
By standardizing units (troy ounces) and timestamps (UTC), Metals-API lets you combine real-time GCK27 with your internal manufacturing, ERP, or treasury data for continuous price discovery and analytics.
Validation and monitoring checklist
- Sanity checks: Ensure 1 / rates.GCK27 ≈ rates.USDGCK27 when both are present.
- Non-decreasing “as of” times: The reported timestamp should not move backward; if it does, retain the latest good record and log a warning.
- Outlier filters: Flag jumps above a practical percentile threshold as “requires review,” but don’t silently discard.
- Observability: Log symbol, USD/oz, timestamp UTC, and request latency for every pull. Emit metric counters for success/failure and cache hits.
Where to go next
- Explore more fields and endpoints: Metals-API Documentation.
- Confirm symbol formatting and categories (including futures-style contracts): Metals-API Supported Symbols.
- Sign up for an API key and configure your environment: Register.
- If you need managed connectivity and pricing delivery options, review available programs at MCP.
General site links for context and updates: Metals-API home and the developer resources on metals-api.com.
Troubleshooting common GCK27 integration issues
- Seeing ounces per USD instead of USD per ounce: Use rates.USDGCK27 if available. Otherwise compute 1 / rates.GCK27.
- Stale timestamps on weekends: Futures markets observe closures. Serve the latest good value, show the “as of” time, and avoid triggering false alerts during known closures.
- Large response payloads: Limit symbols in your query to just GCK27 (as shown) to minimize bandwidth and parsing cost.
- Rounding errors: Keep full-precision decimals in storage; round only for display.
FAQ
-
Q: Which field should I store for “USD per troy ounce” of Gold May 2027?
A: Store rates.USDGCK27 if present. If not, compute and store 1 / rates.GCK27.
-
Q: What units does Metals-API use for gold quotes?
A: Troy ounces. Convert to grams with 1 ozt = 31.1034768 g.
-
Q: How do I handle timestamps?
A: The timestamp is Unix epoch seconds in UTC. Display the “as of” time in UTC or convert explicitly to your local timezone.
-
Q: Can I backfill a chart for GCK27?
A: Yes—use Historical or Time-series endpoints for GCK27 if supported for your plan. See the exact request shapes in the Documentation.
-
Q: Is there a free trial?
A: No. Create an account to obtain an API key: use the Register link below.
Ready to ship your GCK27 integration? Create your API key now and wire the Latest endpoint into your PHP service: Register. For implementation references, parameters, and examples, keep the Documentation open, check the Symbols list for GCK27, and explore delivery options at MCP.
Additional reading: