Use FXMacroData in Smartsheet
Keep official macro indicators, FX rates, commodities, release calendars and COT positioning in a Smartsheet sheet. Every route runs server-side, on your own scheduler or on Smartsheet's servers, so your API key never sits in a browser.
What you can do
| Option | Best for | Runs in | Smartsheet plan |
|---|---|---|---|
| A. Sync tool | Full history of any dataset, with a typed sheet created for you | Your machine, a server or CI, on a schedule | Any plan with API access |
| B. Bridge scheduled refresh | Keeping the newest release current with no script to host | Smartsheet Bridge, on a schedule | Bridge with the Call API utility |
| C. Bridge release webhook | A row the moment a release is published | FXMacroData calls a Bridge workflow trigger | Bridge |
| D. AI assistants | Reading a series and writing rows in plain language | An MCP client connected to both services | Smartsheet's MCP server |
Free USD data
Without an API key, USD indicators, the USD release calendar and USD COT positioning are available for the last 90 days, with a 15-minute delay after each release.
Subscription data
Other currencies, FX rates, commodities, full history and webhooks need an API key from a subscription.
Key handling
The sync tool reads your key from an environment variable and sends it in the X-API-Key header. In Bridge it lives in the Call API profile's secret header. It is never written to a URL.
Option A
Sync tool
fxmd_smartsheet_sync.py reads one FXMacroData dataset, creates the sheet with typed columns if it does not exist, and upserts rows matched on the primary Key column: new releases are added, revised values are updated, and unchanged rows are left alone. It needs Python 3.8 or later and uses only the standard library.
- Create a Smartsheet API access token under Account > Personal settings > API access. API access needs a paid Smartsheet plan.
- Download
fxmd_smartsheet_sync.pyand setSMARTSHEET_ACCESS_TOKEN, plusFXMD_API_KEYfor subscription data. - Run it once with a workspace or folder ID to create the sheet, or with
--sheet-idto fill a sheet you already have. - Schedule the same command with cron, Task Scheduler or a CI job.
export SMARTSHEET_ACCESS_TOKEN=YOUR_SMARTSHEET_TOKEN
export FXMD_API_KEY=YOUR_API_KEY # optional for USD indicators, calendar and COT
# Find or create "FXMacroData USD inflation" in a workspace and upsert rows
python fxmd_smartsheet_sync.py indicator --currency usd --indicator inflation \
--workspace-id 1234567890123456
# Other datasets
python fxmd_smartsheet_sync.py forex --base eur --quote usd --folder-id 2345678901234567
python fxmd_smartsheet_sync.py commodity --commodity gold --sheet-id 3456789012345678
python fxmd_smartsheet_sync.py calendar --currency gbp --workspace-id 1234567890123456
python fxmd_smartsheet_sync.py cot --currency jpy --workspace-id 1234567890123456
# Preview the rows without touching Smartsheet (no token needed)
python fxmd_smartsheet_sync.py indicator --currency usd --indicator gdp --dry-run
Options
| Option | Meaning |
|---|---|
--sheet-id | Upsert into an existing sheet. It needs a Text/Number column named Key; missing data columns are added. |
--workspace-id, --folder-id | Find the sheet by name there, or create it with typed columns. |
--sheet-name | Override the default name, such as FXMacroData USD inflation or FXMacroData EURUSD. |
--start-date, --end-date | Limit the history, YYYY-MM-DD. |
--max-rows | Rows to read from FXMacroData, default 5,000, maximum 20,000. |
--region | us (default), eu, au or gov, or set SMARTSHEET_REGION. A token only works on its own Smartsheet instance. |
--batch-size | Rows per add or update request, default and maximum 500. |
--dry-run | Print the rows as JSON instead of writing. |
What it writes
| Dataset | Columns | Key example |
|---|---|---|
indicator | Key, Date, Value, Previous, Change, Released at (UTC), Currency, Indicator | usd:inflation:2026-09-30 |
forex | Key, Date, Rate, Open, High, Low, Close, Pair | fx:eurusd:2026-09-01 |
commodity | Key, Date, Value, Commodity | commodity:gold:2026-09-01 |
calendar | Key, Release, Name, Scheduled date, Scheduled at (UTC), Reference period, Importance (dropdown: high, medium, low), Currency | The calendar event ID |
cot | Key, Date, Open interest, Non-commercial net, Commercial net, Leveraged funds net, Asset manager net, Dealer net, Released at (UTC) | usd:cot:2026-09-01 |
Date columns are typed as dates and numbers are written as numbers. Smartsheet's API cannot create date-time columns, so release times are ISO 8601 UTC text. Indicator keys match the record_key of FXMacroData release webhooks, so the sync tool and the Bridge workflows can share a sheet.
Smartsheet allows 300 requests per minute per token. The tool retries rate limits and temporary errors with backoff, and never retries row or sheet creation, so a retry cannot create duplicates. A sheet holds at most 500,000 cells; the tool stops before a write that would pass that limit, so use --start-date or a new sheet for very long histories. Only changed rows are rewritten, so a scheduled run usually costs a few requests.
# Every hour at minute 5 5 * * * * /usr/bin/python3 /opt/fxmd/fxmd_smartsheet_sync.py indicator --currency usd --indicator inflation --sheet-id 3456789012345678
Keep the tokens in your scheduler's secret store rather than in the crontab.
Option B
Smartsheet Bridge scheduled refresh
A Bridge workflow fetches the latest release on a schedule and adds or updates the matching row. It runs on Smartsheet's servers, so there is no script to host. Backfill history once with the sync tool, then let Bridge keep the newest rows current.
- Create the sheet with the sync tool, for example
indicator --currency usd --indicator inflation --workspace-id <workspace id>, and register the Smartsheet integration in Bridge with an account that can edit it. - Call API profile. Add a profile named
FXMacroDatawith base URLhttps://api.fxmacrodata.comand a secret headerX-API-Keyholding your key. Leave the header out for free USD data. - Trigger. Create a workflow with a Schedule trigger. Hourly suits most indicators; daily is enough for monthly data.
- Fetch latest. Add Make API Call with the
FXMacroDataprofile, methodGET, endpointv1/announcements/usd/inflationand form parametersfields=compactandlimit=1. Tick the option to stop on an API error. Run the workflow once and open the Run Log:data > 0holdsdate,val,previous_value,change_from_previousandannouncement_datetime. - Find row. Add Smartsheet > Search Sheet filtering
Keyequalsusd:inflation:followed by thedatereference from the previous step. - Exists? Add a Match junction: one path when a row is found, one when it is not.
- Update existing: Update Row with the found row ID, setting Value, Previous and Change. This picks up revisions.
- Add new: Add Row with Key, Date, Value, Previous, Change, Released at (UTC), Currency and Indicator.
announcement_datetime from the API is Unix seconds, while the sync tool writes ISO 8601; either works in a Text/Number column. To track more series, clone the workflow and change the endpoint and Key prefix, or call one child workflow per series with Run Child Workflow. Bridge has no workflow import file; scheduled-refresh.blueprint.json lists every module and field in one place as a build reference.
Option C
Release webhook into a Bridge workflow
FXMacroData sends a webhook the moment a release is stored. A Bridge workflow trigger URL accepts any JSON POST and exposes the body as runtime references, so the standard signed JSON webhook works without a special preset. Webhook subscriptions need an active paid API key.
- In Bridge, open Utilities > Inbound Webhooks, add a Workflow Trigger for a new workflow, and copy its request URL. Treat it as a secret: anyone with the URL can start the workflow.
- In API management, open Webhooks, choose Your server (signed JSON), paste the Bridge URL, optionally limit it to the currencies and indicators you want, and create the webhook. Or create it with the API, as below.
- Send the sample body below to the trigger URL so Bridge can show its references before the next release.
- Build the workflow: Search Sheet with
Keyequals{{runtime.data.currency}}:{{runtime.data.indicator}}:{{runtime.data.latest_announcement.date}}, a Match junction, then Update Row with Value from{{runtime.data.latest_announcement.val}}, or Add Row with Key, Date, Value, Released at (UTC), Currency and Indicator from the same references.
Create the subscription with the API
curl -X POST "https://api.fxmacrodata.com/v1/webhooks/subscriptions" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "BRIDGE_TRIGGER_URL",
"destination": "generic",
"events": ["announcement"],
"currencies": ["usd"],
"indicators": ["inflation"],
"description": "Smartsheet Bridge"
}'
Leave out currencies or indicators to receive every release.
Sample body for testing the trigger
{
"id": "usd_inflation_1791981000",
"event": "announcement",
"data": {
"event_id": "usd_inflation_1791981000",
"currency": "usd",
"indicator": "inflation",
"records_written": 1,
"latest_announcement": {
"date": "2026-09-30",
"val": 3.7,
"announcement_datetime": "2026-10-14T12:30:00Z"
}
}
}
- Every delivery carries an
X-FXMD-Signatureheader, but Bridge cannot check HMAC signatures, so the secrecy of the trigger URL is what protects the workflow. If the URL leaks, delete the trigger in Bridge, create a new one, and update the subscription withPATCH /v1/webhooks/subscriptions/{id}. - Use a plain Workflow Trigger. Advanced triggers that require the
Inbound-Webhook-Secretheader cannot be used, because FXMacroData webhooks do not send custom headers. - Delivery history and status codes are available from
GET /v1/webhooks/deliveriesand in webhook delivery logs.
Option D
AI assistants with both MCP servers
Connect an MCP client to the FXMacroData MCP server and to Smartsheet's MCP server, then ask it to read a series from one and write rows through the other, with your own permissions on both.
https://mcp.fxmacrodata.com/mcp
USD data works without a key. Setup for each client is in the MCP server guide.
Related docs
Questions about a Smartsheet setup? Contact info@fxmacrodata.com.