API to Get the Surat Silver (SURA-XAG) - Per Gram Price - REST endpoint example

Metals-API 10 min read
API to Get the Surat Silver (SURA-XAG) - Per Gram Price - REST endpoint example

You need the live Surat silver price per gram for checkout pricing, hedging, or dashboards, and you want to pull it programmatically via the SURA-XAG symbol. By the end of this guide you’ll know which endpoint to call for SURA-XAG, how to handle the API’s restriction error, and how to derive a per-gram price with correct units, caching, and edge-case handling.

What SURA-XAG is and where it fits in your stack

SURA-XAG represents the silver price for the Surat (India) market. Developers use this city-specific feed to align local retail pricing, jewelry manufacturing inputs, and logistics workflows with on-the-ground market reality instead of relying solely on global benchmarks.

Illustration: API to Get the Surat Silver (SURA-XAG) - Per Gram Price - REST endpoint example

Silver is embedded across manufacturing and smart industry workflows—from photovoltaic cells and high-conductivity components to medical devices and advanced imaging. For ERP and MES systems that must cost, quote, and reconcile in near real time, bringing a city-level series like SURA-XAG into your data pipeline can meaningfully reduce pricing latency and manual overrides. For quant dashboards, this symbol enables localized basis tracking versus global XAG, aiding spread analysis and inventory decisions.

Important: SURA-XAG is restricted on the “latest” endpoint

If you try to query SURA-XAG on the standard latest endpoint, you will receive a restriction error. Here’s a copy/pasteable example and the exact JSON you should expect to handle in production.

curl -s "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&symbols=SURA-XAG"

Official API response (error envelope):

{"success":false,"error":{"code":403,"type":"restricted_symbols","info":"The specified symbols are restricted to the gold-price-india endpoint only.","restricted_symbols":["SURA-XAG"],"endpoint_required":"\/api\/gold-price-india","message":"Indian gold city symbols can only be used with the \/api\/gold-price-india endpoint."}}

What matters in the error:

  • error.type: restricted_symbols — you attempted to use a symbol not allowed on this endpoint.
  • error.endpoint_required: /api/gold-price-india — SURA-XAG belongs to this specialized endpoint.
  • error.restricted_symbols: ["SURA-XAG"] — confirms which symbol triggered the restriction.
  • error.message/info — human-readable context for logs and alerts.

The fix is to query the dedicated endpoint indicated in endpoint_required. See the Metals-API Documentation for parameter details, authentication, and response shape for that endpoint.

Call the correct endpoint for SURA-XAG

Per the error payload, Indian city symbols like SURA-XAG are only available via the gold-price-india endpoint. Use your API key and pass the symbol there. If you haven’t provisioned an API key yet, you can Register to obtain one. Note: Metals-API does not offer a free trial; plans (for example, Copper Monthly at $19.99/mo) are available on the site.

Example request pattern

Replace YOUR_API_KEY with your key. The symbol stays exactly SURA-XAG.

curl -s "https://metals-api.com/api/gold-price-india?access_key=YOUR_API_KEY&symbols=SURA-XAG"

Because the structure and fields for this specialized endpoint are documented separately, use the official docs to confirm parameters, supported symbols, and units returned. Start here: Endpoint reference and examples. Also verify availability on the Metals-API Supported Symbols page to keep your integration future-proof if symbol coverage changes.

Per-gram pricing, base currency, and unit math

Metals-API responses include a unit descriptor and a base currency. For core endpoints:

  • Base is USD by default, unless you set a different base for supported endpoints.
  • Rates are often quoted as metal units per 1 USD. For example, on latest, rates.XAG is “troy ounces per 1 USD”.
  • To convert that to the more familiar USD per troy ounce, invert the rate: USD/oz = 1 / rates.XAG. Some responses may also provide USDXAG (USD per ounce). Always check the response payload and unit field.

Per-gram conversion when your rate is per troy ounce:

  • 1 troy ounce = 31.1034768 grams (see reference: troy weight).
  • If you have USD per troy ounce, then USD per gram = (USD per troy ounce) / 31.1034768.
  • If you have metal per USD (e.g., ounces per 1 USD), first invert to get USD per ounce, then divide by 31.1034768.

City feeds like SURA-XAG may return per-gram values directly or with their own unit field—always branch your logic on the unit property in the response. If the unit is “per troy ounce,” apply the conversion. If it is “per gram” or “per kilogram,” adjust accordingly (divide by 1,000 to go kg→g).

End-to-end example: request, handle the restriction, then price per gram

The following Python sample demonstrates how to:

  1. Call the latest endpoint with SURA-XAG (to illustrate the restriction you’ll encounter if you try the wrong endpoint).
  2. Parse the official error envelope.
  3. Document how you would branch to the correct gold-price-india endpoint and compute a per-gram price once you have a valid rate and unit.
import requests
from decimal import Decimal, ROUND_HALF_UP

API_KEY = "YOUR_API_KEY"

def to_usd_per_gram_from_oz_per_usd(oz_per_usd: Decimal) -> Decimal:
# Invert to get USD per troy ounce, then divide by grams per troy ounce.
USD_PER_OZ = Decimal(1) / oz_per_usd
GRAMS_PER_TROY_OUNCE = Decimal("31.1034768")
return (USD_PER_OZ / GRAMS_PER_TROY_OUNCE).quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP)

def fetch_latest_sura_xag_wrong_endpoint():
url = "https://metals-api.com/api/latest"
params = {"access_key": API_KEY, "symbols": "SURA-XAG"}
r = requests.get(url, params=params, timeout=10)
r.raise_for_status()
return r.json()

data = fetch_latest_sura_xag_wrong_endpoint()

if not data.get("success", False):
err = data.get("error", {})
print(f"[{err.get('code')}] {err.get('type')}: {err.get('message')}")
# Expected: restricted_symbols - must use /api/gold-price-india
endpoint_required = err.get("endpoint_required")
print(f"Use endpoint: {endpoint_required}")

# How you would proceed:
# 1) Call the indicated endpoint for SURA-XAG:
# requests.get("https://metals-api.com" + endpoint_required, params={"access_key": API_KEY, "symbols": "SURA-XAG"})
# 2) Inspect the response:
# - Read 'unit' to determine if it's 'per gram', 'per troy ounce', etc.
# - If per troy ounce and base is USD, convert to USD/gram using 31.1034768.
# 3) If you need local currency (e.g., INR/gram) and the feed is USD-based, convert via the API's conversion features,
# or your own FX feed, then present INR/gram in your app.
else:
# If this ever succeeded (it won't for SURA-XAG on /latest), here's the general approach:
base = data.get("base", "USD")
unit = data.get("unit", "")
rates = data.get("rates", {})
oz_per_usd = Decimal(str(rates.get("SURA-XAG")))
usd_per_gram = to_usd_per_gram_from_oz_per_usd(oz_per_usd)
print(f"Base={base}, Unit={unit}, USD/gram (approx): {usd_per_gram}")

Key takeaways in this flow:

  • Always check success and branch on error.type; do not assume data arrives.
  • Use endpoint_required to re-route your call automatically.
  • Compute per-gram only after you verify the unit and base in the response.

One more time: why the “latest” call fails for SURA-XAG

Here is the exact JSON you must handle if you accidentally use SURA-XAG on the latest endpoint. Log this as a structured error and re-route to the gold-price-india endpoint.

{"success":false,"error":{"code":403,"type":"restricted_symbols","info":"The specified symbols are restricted to the gold-price-india endpoint only.","restricted_symbols":["SURA-XAG"],"endpoint_required":"\/api\/gold-price-india","message":"Indian gold city symbols can only be used with the \/api\/gold-price-india endpoint."}}

For production services, add a small symbol-to-endpoint router so this becomes a one-time setup task rather than a recurring failure pattern. Maintain your own allowlist/denylist and sync it against the current symbols catalog.

Practical details that will save you time

  • Units and troy ounces: Many metals feeds quote “per troy ounce.” Convert to grams with 31.1034768 g/oz. If a feed returns per kilogram, divide by 1,000 to get per gram. Always branch logic on the response’s unit field.
  • Base currency: Default base is USD. If the endpoint returns metal per USD, invert to get USD per unit. When presenting local currency (e.g., INR/gram), either use the API’s conversion capabilities (see the docs) or blend with a trusted FX source.
  • Timestamps and timezone: The sample payloads show Unix timestamps and an ISO date. Treat timestamps as Unix epoch seconds in UTC. Display in your user’s timezone only at the UI layer to avoid cache fragmentation.
  • Caching and request volume: Cache identical queries (same endpoint, parameters) for the duration appropriate to your plan’s update frequency. For shopping-cart price checks, many teams cache for 60–120 seconds and invalidate on cart updates. For research dashboards, 1–5 minute caches are typical. Respect the plan’s stated update cadence in the docs.
  • Market closures, weekends, and holidays: Metals pricing can appear “stale” across certain hours or days. Your code should tolerate unchanged timestamps/dates and show the most recent value with a clear “as of” time. Avoid hard failures if no new tick arrives.
  • Numerical stability: Use decimal math for currency and per-gram calculations to avoid floating-point rounding issues. Quantize to a sensible precision (e.g., 0.01 for currency) before display and order routing.
  • Monitoring: Alert on error.type changes and rising 4xx/5xx rates. The restricted_symbols pattern is expected when symbols route to specialized endpoints; treat it as info-level once you add routing.

Working with related data for validation and analysis

Many teams validate city-level silver prices against global benchmarks and industrial use trends. For benchmarking, consider cross-checking with recognized sources such as the LBMA price data. For FX alignment or stress-testing conversion logic, reference public aggregates like the BIS statistics portal. These are not drop-in replacements for the API but can be helpful for sanity checks and regression tests.

Optional: Using time series or fluctuation when comparing SURA-XAG to global XAG

When you need to analyze day-over-day moves or build chart backfills, the time-series and fluctuation endpoints are useful. For SURA-XAG, continue to call its specialized endpoint for the spot price. For broader historical context, consult the endpoint documentation first to confirm symbol availability for each historical feature before requesting data.

Copy-ready curl you can run now (shows the restriction)

Run this to see the exact restriction response for SURA-XAG on the latest endpoint:

curl -s "https://metals-api.com/api/latest?access_key=YOUR_API_KEY&symbols=SURA-XAG"

Then, switch to the indicated endpoint:

curl -s "https://metals-api.com/api/gold-price-india?access_key=YOUR_API_KEY&symbols=SURA-XAG"

Consult the Documentation for the exact response fields to parse for the gold-price-india endpoint.

Why per-gram SURA-XAG matters for smart manufacturing

Digital manufacturing systems increasingly link BOMs, supplier portals, and WIP tracking to market data. Silver content in solder, plating, switches, and sensors makes per-gram pricing essential to costed bills and variance analysis. With SURA-XAG, a Surat-based operation can quote in line with local reality, run weighted-average costing updates intraday, and detect spread anomalies versus global XAG to time purchases or hedge exposure.

For analytics stacks, merge SURA-XAG into your data lake with a clear unit field and per-gram normalization. Tag each record with timestamp (UTC), source endpoint, symbol, and any conversions performed (e.g., oz→g, USD→INR) to keep downstream models auditable.

FAQ

Q: Why do I get restricted_symbols for SURA-XAG on /api/latest?
A: SURA-XAG is an Indian city symbol and must be queried via /api/gold-price-india. The error response includes endpoint_required so your client can re-route automatically.

Q: How do I convert to per gram?
A: Check the unit field in the response. If it’s per troy ounce and base is USD, invert if needed to get USD/oz, then divide by 31.1034768 to get USD/gram. If it’s per kilogram, divide by 1,000. If the endpoint already returns per gram, no conversion is needed.

Q: What timezone are the timestamps?
A: Treat Unix timestamps as UTC. Display local time only at the UI layer to avoid cache fragmentation and data mismatches.

Q: Can I test without paying?
A: Metals-API does not offer a free trial. You’ll need an API key from a paid plan. For plan details, see the site. Copper Monthly is $19.99/mo as a reference point.

Q: How often are prices updated?
A: Update frequency depends on your subscription plan and endpoint. See the Documentation for per-endpoint behavior and your plan’s refresh cadence.

Get your key and wire this into your pricing or analytics stack today: Register. For multi-connector workflows and productization support, check out MCP. If you are validating symbol coverage or planning routing rules, start with the Symbols list.