Download the silver portfolio workbook, open it in Google Sheets, and use the companion Apps Script to refresh XAG-USD-SPOT every six hours from goldprice.dev. Store your API key in Script Properties, never in cells. The workbook converts troy ounces to grams, keeps purity and cost per holding, and calculates indicative spot value and change.
Download and import the workbook
Download the silver portfolio workbook, upload it to Google Drive, and choose Open with → Google Sheets. Under File → Settings, set the time zone to GMT+00:00 (UTC) so timestamps match the labels. Replace the example holdings and refresh the sample quote before using the valuation. The formulas calculate fine silver grams, spot value, change, and change percentage.
Keep the API key out of cells
XAG spot is on every plan, including Free. In the Sheet, open Extensions → Apps Script → Project Settings → Script properties and add SILVER_API_KEY. Store the key there, rather than in a visible cell or formula. A six-hour refresh makes four calls per day, about 120 calls per 30-day month.
Paste the scheduled refresh script
Download the companion Code.gs and paste it into the Apps Script editor. Run installSilverRefresh once and approve the Google permissions. It replaces duplicate refresh triggers, fetches the authenticated XAG quote, validates the symbol, currency, price, and timestamp, then updates the Price Data cells together.
const ENDPOINT = "https://api.goldprice.dev/v1/spot/XAG-USD-SPOT";function fetchSilverQuote_() { const key = PropertiesService.getScriptProperties().getProperty("SILVER_API_KEY"); if (!key) throw new Error("Add SILVER_API_KEY in Script properties."); const response = UrlFetchApp.fetch(ENDPOINT, { headers: { Authorization: "Bearer " + key }, muteHttpExceptions: true, }); const status = response.getResponseCode(); if (status === 403) throw new Error("Access denied; check the key and symbol."); if (status === 429) throw new Error("Rate limit reached; wait before retrying."); if (status !== 200) throw new Error("Goldprice returned HTTP " + status); const data = JSON.parse(response.getContentText()); if (data.is_stale) throw new Error("The API marked this quote stale; the previous valid quote remains in the sheet."); const value = Number(data.price); if (data.symbol !== "XAG" || data.quote_currency !== "USD" || !Number.isFinite(value) || value <= 0) { throw new Error("Invalid XAG/USD response"); } return data;}Check the refreshed valuation
After the first refresh, Price Data shows the quote timestamp, silver price per troy ounce, and the calculated price per gram. Portfolio references those cells and multiplies fine silver grams by the current per-gram spot price. The result is an indicative spot valuation, not a dealer buyback quote or appraisal.
Set a schedule that fits your quota
The script uses one request per scheduled refresh. Six-hour refreshes use about 120 calls/month; hourly refreshes use about 720. Add retries only for transient errors and keep the schedule below your plan quota. If a shared workbook has many editors, use a server-side proxy and keep the API key out of the Sheet.
ScriptApp.newTrigger("refreshSilverData") .timeBased() .everyHours(6) .create();Expected output
{ "symbol": "XAG", "quote_currency": "USD", "price": "32.50", "computed_at": "2026-09-29T10:00:00+00:00"}Price Data shows the authenticated quote and timestamp; Portfolio shows fine silver grams, current spot value, change, and change percentage for each holding.
Common errors
| Code | What you see | Fix |
|---|---|---|
| 401 | Apps Script reports HTTP 401. | Check the exact SILVER_API_KEY Script Property and keep the Bearer prefix in the request header. |
| 403 | Apps Script reports HTTP 403. | XAG spot is included on Free. Check the key and requested symbol. |
| 429 | The scheduled refresh reports HTTP 429. | Remove duplicate triggers, keep the six-hour schedule, and wait for the retry window. One refresh should make one API call. |
Going further
- Add a second sheet that records each successful quote timestamp for an audit trail.
- Add a local-currency conversion through a server-side service that keeps credentials private.
- Compare the indicative spot value with separately collected dealer sell and buyback quotes.