How to get live gold prices in Power BI

Pull live gold prices into Power BI via Power Query M, with scheduled refresh in the Service. One refresh per workspace, 8/day on Pro.

Updated

To get live gold prices in Power BI, paste a Power Query M query that calls api.goldprice.dev/v1/spot/XAU-USD-SPOT with your API key in the X-API-Key header, then publish to the Service and configure scheduled refresh. The free tier covers 1,000 calls/month, no credit card. Tested April 2026 against Power BI Desktop + Service. Below: query, refresh setup, credentials walkthrough, and multi-currency variants.

  1. 1.Get your goldprice.dev API key

    Sign up for a free account at goldprice.dev/onboarding. Your dashboard shows a key starting with goldprice_live_. Copy it — you will paste it as a Power Query parameter in the next step.

    The free tier includes 1,000 calls/month and 13 supported currencies. No credit card required.

    Get your free API key1,000 calls/mo, no credit card
    Sign up free →
  2. 2.Open Power Query in Power BI Desktop

    From the Power BI Desktop ribbon, click Home → Transform Data to open the Power Query Editor. Then click Home → New Source → Blank Query, then View → Advanced Editor. You will paste the M query into that text box.

    Power Query M is the only path that survives publishing to the Power BI Service with scheduled refresh — DAX cannot make HTTP calls.

  3. 3.Paste the GoldPrice M query

    Replace the editor contents with the query below, then click Done. Rename the query GoldPrice in the right rail. The RelativePath argument is required for scheduled refresh in the Service — without it, refresh fails with a credentials error.

    POWERQUERY · Power Query · Advanced Editor
    // power-bi: Power Query M query "GoldPrice"
    // curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOT
    // Replace ApiKey with your goldprice.dev key from /onboarding
    let
        ApiKey = "goldprice_live_replace_with_your_key_here",
        Symbol = "XAU-USD-SPOT",
        Source = Json.Document(
            Web.Contents(
                "https://api.goldprice.dev",
                [
                    RelativePath = "v1/spot/" & Symbol,
                    Headers = [#"X-API-Key" = ApiKey],
                    ManualStatusHandling = {401, 429}
                ]
            )
        ),
        Result = #table(
            {"field", "value"},
            {
                {"symbol", Source[symbol] & "-" & Source[quote_currency]},
                {"price", Number.FromText(Source[price])},
                {"bid", Number.FromText(Source[bid])},
                {"ask", Number.FromText(Source[ask])},
                {"computed_at", Source[computed_at]},
                {"is_stale", Source[is_stale]}
            }
        )
    in
        Result
  4. 4.Publish and configure scheduled refresh

    Save the report and click Home → Publish to push to the Service. In the Service, open Workspace → Datasets → Settings. Under Data source credentials, choose Anonymous for the https://api.goldprice.dev source (your key travels in the header, not the URL). Under Scheduled refresh, toggle on and pick a cadence — Pro supports up to 8 refreshes/day, Premium up to 48.

  5. 5.Switch currency or metal

    Edit the query in Desktop, change the Symbol parameter, save, and re-publish. For multi-currency dashboards, duplicate the query under different names (one per symbol) so each renders as its own visual.

    POWERQUERY · Power Query · multi-currency variants
    // USD spot — default
    Symbol = "XAU-USD-SPOT"
    
    // INR — Indian gold market (largest retail gold-search globally)
    Symbol = "XAU-INR-SPOT"
    
    // EUR — European pricing surfaces
    Symbol = "XAU-EUR-SPOT"
    
    // Silver in USD
    Symbol = "XAG-USD-SPOT"

Expected output

The API returns this shape:

JSON · GET /v1/spot/XAU-USD-SPOT
{
  "symbol": "XAU",
  "quote_currency": "USD",
  "unit": "troy_ounce",
  "contract_type": "spot",
  "price": "4726.01",
  "bid": "4726.68",
  "ask": "4725.33",
  "is_stale": false,
  "divergence_flag": false,
  "computed_at": "2026-04-27T04:49:01.706844+00:00",
  "sources": [
    {
      "source": "wgc.fsapi.usd",
      "display_name": "World Gold Council (live spot)",
      "price": "4726.01",
      "is_stale": false,
      "timestamp": "2026-04-27T04:47:24+00:00"
    }
    /* + cmc.paxg + cmc.xaut entries — full sources[] in live response */
  ],
  "value_stale": false,
  "price_gram_24k": "151.9447",
  "open_price": "4681.305",
  "high_price": "4729.56",
  "low_price": "4672.927",
  "prev_close_price": "4681.302",
  "ch": "44.6260",
  "chp": "0.9533",
  "open_time": 1777248000
}

The dataset will show six rows when previewed in Desktop. Drag the price field onto a card visual for the headline number; use computed_at on a tooltip so report viewers see freshness.

Common errors

CodeSymptomFix
401Refresh fails in the Service with The credentials provided for the Web source are invalidAPI key missing, invalid, or rotated. In Dataset settings → Data source credentials, click Edit credentials for api.goldprice.dev, choose Anonymous, and click Sign in. Then edit the query in Desktop, paste a fresh key into ApiKey, and re-publish.
429Sporadic refresh failures with 429 Too Many RequestsYou hit the per-minute cap. Each scheduled refresh = 1 call per query in the dataset. If you have 10 currency-specific queries refreshing 8 times/day, that is 80 calls/day = 2,400/month — over the free tier. Reduce refresh cadence, consolidate queries, or upgrade — see /pricing for Basic and Pro tiers.
N/ADesktop refresh works but Service refresh fails with Please specify how to connectYou connected to the full URL instead of base + RelativePath. The Service credentials resolver matches against the base origin only. Edit the query and copy the canonical version above verbatim — base URL goes as Web.Contents's first argument, the path goes inside [RelativePath = ...].

FAQ

How often does the price update?

The spot endpoint refreshes every 60 seconds (Pyth + WGC + CME aggregation). Power BI does not poll on its own — the dataset refreshes on the schedule you configure. Pro caps at 8 refreshes/day; Premium caps at 48.

Will this fit the free tier with auto-refresh?

Yes for typical dashboards. One query × 8 refreshes/day × 30 days = 240 calls/month, well inside the 1,000-call free tier. A 5-query multi-currency dashboard at 8/day = 1,200/month — just over. Either reduce to 4-6 refreshes/day or upgrade — see /pricing for Basic and Pro tiers.

Do I need a Power BI Pro license?

Yes for scheduled refresh in the Service — a Pro license is required to publish a dataset that refreshes on a schedule. Power BI Desktop alone is free, but it only refreshes on your machine. For internal dashboards, every viewer also needs Pro unless the workspace is in Premium capacity.

Can I use this commercially?

The Free tier is for personal use. For commercial dashboards (internal reporting at work, embedded analytics in products you sell), upgrade to Basic or Pro — see /pricing.

What metals are supported?

Gold (XAU), silver (XAG), copper (HG), platinum (XPT), palladium (XPD). Substitute the metal code in the Symbol parameter, e.g. XAG-USD-SPOT.

Is the free tier really free?

Yes — 1,000 calls/month, no credit card, no expiration. Get the key at /onboarding.

Can I have Claude write this for me?

Yes. Open Claude Desktop with the goldprice.dev MCP server installed and ask: Write a Power Query M query for Power BI that calls the goldprice.dev /v1/spot endpoint. Use Web.Contents with RelativePath so scheduled refresh works in the Service. Return symbol, price, bid, ask, and timestamp as a table. The MCP server gives Claude the live schema, so generated code uses correct field names on first try.

Going further

  • Build a multi-metal scorecard: one query per metal (XAU, XAG, HG, XPT, XPD) feeding a single card-grid visual
  • Add a parameter table — store ApiKey and supported symbols so non-technical authors can swap inputs without touching M code
  • Track price-vs-prev-close as a KPI visual using price - prev_close_price for a daily change indicator
  • Pull /v1/history/XAU-USD-SPOT?days=30 into a separate query for a sparkline
  • Embed the report in SharePoint or Teams with row-level security on the price column

Next steps

Try the same setup in a different platform:

Browse all 6 tutorials →