A country macro panel needs five numbers: inflation, unemployment, GDP growth, the policy rate and the trade balance. Narwhal returns each from its own country route with the period it covers and the day it was released, and the economic calendar gives the time of the next release.
Request the inflation figure for one country
curl -s "https://api.narwhalapi.com/v1/economics/USA/inflation" \
-H "Authorization: Bearer $NARWHAL_API_KEY"{
"country": "USA",
"period": "2026-09",
"year_over_year": "3.7",
"month_over_month": "0.6",
"year_to_date": "4.0",
"released_on": "2026-10-14"
}year_over_year is the headline number for a tile. period is the month the figure describes and released_on is the day it was published, so a tile can print both. Values arrive as decimal strings, so convert them before you chart them.
The other four panel lines come from sibling routes with the same shape. Each returns the latest period when you send no date.
| Panel line | Route | Headline field | Period format |
|---|---|---|---|
| Inflation | /v1/economics/{country}/inflation | year_over_year | 2026-09 |
| Unemployment | /v1/economics/{country}/unemployment | rate | 2026-09 |
| GDP growth | /v1/economics/{country}/gdp-growth | year_over_year | 2026-Q3 |
| Policy rate | /v1/economics/{country}/central-bank/policy-rate | lower_bound and upper_bound, or rate | none, see effective_on |
| Trade balance | /v1/economics/{country}/trade | balance | 2026-08 |
Handle period and released_on
The five lines do not share a period. For the US the inflation and unemployment responses describe 2026-09, GDP growth describes the quarter 2026-Q3 and the trade response describes 2026-08. Label each tile with its own period and do not line the tiles up by release day.
released_on is the publication date of that figure. Keep it as its own field. A tile that shows only the release date reads as if the figure describes that month, and a tile that shows only the period hides how old the number is.
- The policy rate response has no
period. It carrieseffective_on,observed_onandannounced_on, and any of them can be null. For the US it returnedrate_typeofrangewithlower_bound3.75 andupper_bound4.00, so print the range. A country withrate_typeofpointreturns a singlerate. - The trade response gives
exports,importsandbalanceincurrency, here USD. The balance is exports minus imports, so the US value of -131421164606 means imports were larger. - A country without a series answers 404 with the problem code
series_not_found. Mexico returned that for its policy rate while its inflation, GDP growth and unemployment answered. Show a gap for that line and keep drawing the others.
Add the next release time from the calendar
To know when a tile should change, read GET /v1/economics/calendar for the same country. Each entry has a series_id, the period it will cover and an at time in UTC. The script below pulls the calendar for the next 60 days, picks the earliest at for each line and prints the whole panel.
- Get a key Create an API key and export it as
NARWHAL_API_KEY. The script sends it as a Bearer token. - Run the script It requests the calendar once, then the five data routes. A 404 returns
Noneand printsno datafor that line.import os from datetime import date, timedelta import requests BASE = "https://api.narwhalapi.com" HEAD = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"} country = "USA" def get(path, **params): r = requests.get(BASE + path, params=params, headers=HEAD, timeout=10) if r.status_code == 404: return None r.raise_for_status() return r.json() calendar = get( "/v1/economics/calendar", countries=country, start_date=date.today().isoformat(), end_date=(date.today() + timedelta(days=60)).isoformat(), )["releases"] def next_release(series_id): due = [x["at"] for x in calendar if x["series_id"] == series_id and "at" in x] return min(due) if due else None panel = [ ("Inflation, % y/y", "inflation", "year_over_year", "usa-consumer-prices"), ("Unemployment, %", "unemployment", "rate", "usa-employment-report"), ("GDP growth, % y/y", "gdp-growth", "year_over_year", "usa-gdp"), ("Trade balance, USD", "trade", "balance", "usa-goods-and-services-trade"), ] for label, path, field, series_id in panel: d = get(f"/v1/economics/{country}/{path}") if d is None: print(label, "no data") continue print(label, d[field], d["period"], d["released_on"], next_release(series_id)) rate = get(f"/v1/economics/{country}/central-bank/policy-rate") if rate: print("Policy rate, %", rate["lower_bound"], rate["upper_bound"], rate["effective_on"], next_release("usa-policy-rate-decision")) - Read the output Each printed row holds the value, its
period,released_onand the nextat. Compareatwith the clock to decide when to call the route again.
| Line | Value | Period | Released on | Next release (UTC) |
|---|---|---|---|---|
| Inflation, % y/y | 3.7 | 2026-09 | 2026-10-14 | 2026-11-10T13:30:00Z |
| Unemployment, % | 4.2 | 2026-09 | 2026-10-02 | 2026-11-06T13:30:00Z |
| GDP growth, % y/y | 2.1 | 2026-Q3 | 2026-10-29 | 2026-11-25T13:30:00Z |
| Trade balance, USD | -131421164606 | 2026-08 | 2026-10-06 | 2026-11-04T13:30:00Z |
| Policy rate, % | 3.75 to 4.00 | effective 2026-09-17 | not applicable | 2026-12-09T19:00:00Z |
The calendar entry for GDP on 2026-11-25 has stage of second, so it covers 2026-Q3 again. The panel should show the same period with a possibly different value after that time.
How often should the panel refresh?
Poll the calendar once a day and re-read a line when the clock passes its at time. Between those times the calendar lists no new figure for that line. The at time can move, so read it again on each poll instead of storing it for weeks.
Each entry also carries a status, which is scheduled until the release is out, so a line whose status has changed is worth re-reading even before you reach its next poll.
Which period does a GDP tile show?
The newest quarter that has a figure. In the table above the latest quarter is 2026-Q3, released on 2026-10-29. The route answers with quarter_over_quarter as well, so a tile can show either rate. State which one it is, because the two differ.
Send period=2026-Q3 to read a named quarter and compare it with the latest.
What does a negative trade balance mean?
It means imports exceeded exports in that period. The US response shows exports of 204748660746 and imports of 336169825352, and 204748660746 minus 336169825352 equals the published balance of -131421164606 USD.
Published .