Integration guide for Bangalore Silver (BANG-XAG) - Per Gram Price API in PHP for live quote retrieval
You need to display a live per-gram price for Bangalore Silver in a PHP app. By the end of this guide you will be able to call the Metals-API latest endpoint with the BANG-XAG symbol, handle the restricted-symbols error correctly, and structure your code to fetch the proper city price via the required endpoint, then compute a per-gram value for your UI or pricing logic.
What BANG-XAG represents and why this integration is special
BANG-XAG is the Metals-API symbol for Bangalore silver. City-specific Indian symbols are handled differently than global market symbols. While a standard XAG quote flows through the generic latest endpoint, BANG-XAG is restricted and must be requested through the dedicated India pricing endpoint.
That means your PHP integration should still start with a latest request (so you can programmatically detect restrictions), but it must gracefully switch to the required endpoint for city prices. We will show the exact error envelope you will receive and how to branch your code accordingly.
Before you start, get your API key from Metals-API. See the product overview and plans on the main site at metals-api.com and create credentials here: Register.
Quick reference: units, base currency and the gram conversion you’ll need
- Base currency in Metals-API defaults to USD unless you override it. Response examples here use USD as base.
- Unit: metals are quoted “per troy ounce” (31.1034768 grams). You must convert to grams for per-gram display.
- Inversion basics:
- With base=USD, rates.XAG is ounces per 1 USD (oz/USD).
- The inverse is USDXAG (USD/oz). If your response gives oz/USD, invert it to get a price per ounce in USD.
- Per-gram price in INR (conceptual workflow):
- Obtain a BANG-XAG price using the required endpoint (see below).
- Normalize to a per-ounce figure if needed, then divide by 31.1034768 for per-gram.
- If you receive USD pricing, convert to INR using currency conversion logic (see Documentation for conversion options).
Step 1: Test the latest endpoint with BANG-XAG (expected: restricted_symbols)
Start by calling the latest endpoint for BANG-XAG. This request is useful because it returns a machine-readable error that tells your code which endpoint to use for Indian city symbols.
curl request
curl "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&symbols=BANG-XAG"
Official error response you will receive
{"success":false,"error":{"code":403,"type":"restricted_symbols","info":"The specified symbols are restricted to the gold-price-india endpoint only.","restricted_symbols":["BANG-XAG"],"endpoint_required":"\/api\/gold-price-india","message":"Indian gold city symbols can only be used with the \/api\/gold-price-india endpoint."}}
How to read this response
- success: false — the request cannot return data from the generic latest endpoint for this symbol.
- error.code: 403 — authorization/permission scope issue at the symbol level.
- error.type: restricted_symbols — this tells you the symbol is valid but cannot be used here.
- error.restricted_symbols: ["BANG-XAG"] — the symbol that triggered the restriction.
- error.endpoint_required: /api/gold-price-india — the endpoint you must use to retrieve BANG-XAG.
- error.message and error.info — human-readable guidance that Indian city symbols require the India pricing endpoint.
Step 2: PHP cURL integration for BANG-XAG with graceful error handling
Below is a minimal PHP cURL snippet that calls the latest endpoint for BANG-XAG, parses the error envelope, and signals the calling code to switch to the required endpoint. Keep this as your first check so your application can automatically route city requests correctly.
<?php
$endpoint = "https://metals-api.com/api/latest";
$params = http_build_query([
"access_key" => "YOUR_API_KEY",
"symbols" => "BANG-XAG"
]);
$url = $endpoint . "?" . $params;
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);
if ($curlErr) {
// Network/transport error; retry/backoff strategy recommended.
throw new RuntimeException("cURL error: " . $curlErr);
}
$data = json_decode($response, true);
if (!is_array($data)) {
throw new RuntimeException("Invalid JSON response (HTTP $httpCode): " . $response);
}
if (isset($data["success"]) && $data["success"] === false) {
$err = $data["error"] ?? [];
$type = $err["type"] ?? "unknown_error";
if ($type === "restricted_symbols" && !empty($err["endpoint_required"])) {
// Route to the required endpoint for Indian city symbols
$required = $err["endpoint_required"]; // e.g. "/api/gold-price-india"
// At this point, call the required endpoint with your same symbol (BANG-XAG)
// Ensure you follow the endpoint-specific parameters in the official docs.
// Example (pseudocode):
// $cityUrl = "https://metals-api.com" . $required . "?access_key=YOUR_API_KEY&symbols=BANG-XAG";
// ...perform a new request and parse its response...
echo "BANG-XAG must be requested via: " . $required . PHP_EOL;
exit;
}
// Handle other API errors as appropriate for your application
throw new RuntimeException("API error: " . json_encode($err));
}
// If this branch ever succeeds for other symbols, process $data as normal.
// For BANG-XAG you should not reach here via /api/latest based on the restriction.
print_r($data);
Notes:
- Do not hardcode assumptions about response shapes across endpoints. The India pricing endpoint may return different fields than latest; consult the Documentation.
- Keep the “restricted_symbols” branch generic so the same logic works for other Indian city symbols if you add them later. You can enumerate currently available symbols in the Symbols list.
Step 3: JavaScript fallback logic (detect and reroute)
If your front end (or a Node.js service) needs to fetch a Bangalore Silver quote directly, apply the same restricted-symbols handling. This example calls the latest endpoint and, on the restricted error, instructs your data layer to query the required endpoint instead.
async function fetchBangXag() {
const url = "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&symbols=BANG-XAG";
const res = await fetch(url, { method: "GET" });
const data = await res.json();
if (data && data.success === false && data.error) {
const err = data.error;
if (err.type === "restricted_symbols" && err.endpoint_required) {
// Signal the calling code which API path to use for BANG-XAG
return {
reroute: true,
endpointRequired: err.endpoint_required, // "/api/gold-price-india"
message: err.message
};
}
throw new Error("API error: " + (err.message || err.type));
}
// For non-restricted symbols you would process the data here.
return { reroute: false, payload: data };
}
fetchBangXag()
.then(result => {
if (result.reroute) {
console.log("Use required endpoint:", result.endpointRequired);
// Next step: build and call the required endpoint with symbol=BANG-XAG
// and parse the returned structure as documented.
} else {
console.log("Payload:", result.payload);
}
})
.catch(err => console.error(err));
Step 4: Compute a per-gram price once you have the BANG-XAG quote
City pricing endpoints sometimes return values in different units than global feeds. After you retrieve BANG-XAG from the required endpoint:
- If you have a USD-per-ounce value (USD/oz): per-gram = (USD/oz) / 31.1034768.
- If you have an ounce-per-USD value (oz/USD): first invert to USD/oz, then divide by 31.1034768.
- If the response is in INR or another currency, apply the same conversion math after currency normalization if necessary.
Practical PHP helper (unit math only):
<?php
function usdPerGramFromUsdPerOz(float $usdPerOz): float {
return $usdPerOz / 31.1034768;
}
function usdPerOzFromOzPerUsd(float $ozPerUsd): float {
if ($ozPerUsd <= 0.0) {
throw new InvalidArgumentException("ozPerUsd must be > 0");
}
return 1.0 / $ozPerUsd;
}
Use these helpers after you parse the BANG-XAG payload from the required endpoint, aligning units and currency to your display needs.
Operational details that will save you time
- Timestamps and timezone: API timestamps are Unix epoch seconds. Treat them as UTC for display and caching. Convert to your local time only in the UI layer.
- Caching and request economy:
- Cache city quotes for at least the update cadence of your plan (see plan detail pages) to avoid redundant calls.
- Invalidate on symbol- or currency-switch and when your user explicitly refreshes.
- Non-trading days and weekends: Metals spot markets can be less active on weekends/holidays; expect flat rates or stale timestamps during closures. Use historical or previous business day values if your UI must always show a number, but label them clearly.
- Error handling:
- restricted_symbols: switch to the endpoint in error.endpoint_required.
- Network errors: backoff and retry with jitter; surface a degraded UI state if retries fail.
- Validation: check success === true before accessing data fields.
- Symbol governance: Audit your symbol list periodically using the Symbols endpoint to keep your UI options in sync with availability.
Why Bangalore Silver data matters for manufacturing and smart operations
Silver’s industrial footprint extends from electronics and photovoltaics to medical devices and advanced solders. If you operate a BOM-driven workflow in Bangalore, a city-specific silver feed lets you:
- Hedge or quote precisely for regional supply chains where logistics and local premia matter.
- Automate reorder thresholds by grams, not ounces, directly from city rates.
- Feed ERP/MES with normalized costs per gram, synchronized to UTC timestamps for auditability.
Tie your per-gram feed into demand forecasting, dynamic pricing in e-commerce, or threshold alerts in dashboards. If you manage multiple facilities, align data refresh windows with shift changes to minimize cost variance on work orders.
Choosing endpoints for this use case
For Bangalore Silver (BANG-XAG) you must use the India pricing endpoint indicated by the API when you attempt a latest call. For other data types (historical, time-series, OHLC, bid/ask, or conversions), review the endpoint capabilities and constraints in the Documentation. Only invoke endpoints that support your target symbol set.
If you also maintain global silver analytics (separate from city quotes), plan that code path independently. Keep BANG-XAG logic partitioned so you can respect the endpoint requirement and unit differences.
Security, observability, and deployment tips
- Keep YOUR_API_KEY in secure configuration (environment variables, secrets manager). Do not commit it to your VCS.
- Log request IDs/timestamps and the exact symbol(s) you query. Redact keys in logs.
- Expose health metrics: latency to Metals-API; error counts by type (restricted_symbols, 4xx, 5xx). Alert on anomalies.
- Throttling: centralize your HTTP client and enforce rate-aware queues if you fan out requests across services.
- Version your parsing code per endpoint. If you add new Indian city symbols later, reuse the same restricted-symbols branch.
Validating symbol availability and planning for growth
Symbols evolve. Audit periodically so your UI doesn’t offer stale or unsupported options, and so your backend doesn’t hit avoidable errors. Use the Metals-API Supported Symbols endpoint as your source of truth, and cross-reference with product plans for data update frequency and endpoint access. For programmatic control and vendor management, Metals-API’s MCP page is also useful: MCP.
Putting it together in your application flow
- Call /api/latest with symbols=BANG-XAG to detect if the symbol is restricted. Expect the restricted_symbols error for BANG-XAG.
- Read error.endpoint_required ("/api/gold-price-india") and reissue the request to that endpoint with BANG-XAG as documented.
- Parse the required endpoint’s payload. Identify:
- The price field(s) you need (ensure you know whether they are USD/oz, INR/oz, or another unit).
- The timestamp for cache keys and UI labels (treat as UTC).
- Normalize to per-gram: if your value is per ounce, divide by 31.1034768. If your value is oz/USD, invert first.
- Cache the computed per-gram figure keyed by symbol, currency, and timestamp to reduce calls and stabilize UI.
- Expose a diagnostics endpoint (internal) that replies with last fetch time, endpoint used, and current per-gram value for on-call clarity.
FAQ
Can I use BANG-XAG with the generic latest endpoint?
No. As shown in the official response, BANG-XAG is a restricted city symbol and must be queried via the endpoint indicated in error.endpoint_required ("/api/gold-price-india").
How do I compute a per-gram price from an ounce-based quote?
Divide any per-ounce figure by 31.1034768. If you receive oz/USD, invert it to USD/oz first, then divide by 31.1034768.
What timezone are Metals-API timestamps in?
Treat timestamps as Unix epoch seconds in UTC. Convert in your presentation layer if you need local time.
How should I cache Bangalore Silver quotes?
Cache for at least the update cadence allowed by your plan and purge when your symbol, currency, or endpoint changes. Stamp caches with the API timestamp to avoid mixing values from different sessions.
Is there a free trial?
There is no free trial. Review plans and get an API key via Register. The Copper Monthly plan is listed at $19.99/mo; see the site for details on other plans.
Ready to integrate Bangalore Silver into your stack? Start with the endpoint and symbol references in the Documentation, verify symbol availability via Symbols, and create your API key here: Register. For broader program control, visit MCP.