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 5,000 calls/month, no credit card. Tested April 2026 against Power BI Desktop + Service. Below: query, refresh setup, credentials walkthrough, and multi-currency variants.
Get your goldprice.dev API key
Sign up for a free account at goldprice.dev/onboarding. Your dashboard shows a key starting with ga_live_. Copy it; you will paste it as a Power Query parameter in the next step.
The free tier includes 5,000 calls/month and gold spot in 31 currencies. No credit card required.
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.
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.
// 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 /onboardinglet ApiKey = "ga_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], "en-US")}, {"bid", if Record.HasFields(Source, "bid") and Source[bid] <> null then Number.FromText(Source[bid], "en-US") else null}, {"ask", if Record.HasFields(Source, "ask") and Source[ask] <> null then Number.FromText(Source[ask], "en-US") else null}, {"computed_at", Source[computed_at]}, {"is_stale", Source[is_stale]} } )in ResultPublish 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.
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.
// USD spot, defaultSymbol = "XAU-USD-SPOT"Symbol = "XAU-INR-SPOT"Symbol = "XAU-EUR-SPOT"// Silver in USDSymbol = "XAG-USD-SPOT"Expected output
{ "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"}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
| Code | What you see | Fix |
|---|---|---|
| 401 | Refresh fails in the Service with The credentials provided for the Web source are invalid | API 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. |
| 429 | Sporadic refresh failures with 429 Too Many Requests | You 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, inside Free. Check other queries and retries before increasing cadence; see /pricing for paid plans. |
| N/A | Desktop refresh works but Service refresh fails with Please specify how to connect | You 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 = ...]. |
Going further
- Build a multi-metal scorecard: one query per available metal (XAU, XAG, HG) feeding a single card-grid visual
- Add a parameter table, store
ApiKeyand supported symbols so non-technical authors can swap inputs without touching M code - Track day-over-day change as a KPI visual by pulling yesterday's
closefrom/v1/bars?interval=1dand comparing it to the livepricefield - Pull
/v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...into a separate query for a sparkline - Embed the report in SharePoint or Teams with row-level security on the price column