To move from Alpha Vantage, replace the apikey query parameter with an Authorization: Bearer header and map each function to a Narwhal path. CPI, unemployment, FX, stock quotes, daily bars, metals, oil and crypto have direct equivalents. Technical indicators, options and news sentiment do not.
Who should migrate, and who should stay
Teams move for licence and quota reasons. Alpha Vantage limits free and premium keys to personal, non-commercial use unless you agree otherwise in writing, while the Narwhal Free plan includes commercial app use. The Alpha Vantage free key allows 25 requests a day; Narwhal Free allows 5,000 a month. Alpha Vantage economic series cover the United States only, and Narwhal reads economics for 37 countries. One Narwhal key also works over MCP, which suits agent projects.
Stay with Alpha Vantage for technical indicators, options and news sentiment. It lists 25 or more years of daily history, while Narwhal Free reaches back 12 months, Basic 5 years and Pro full history. Narwhal stocks cover 42 exchanges, and Tokyo is not one of them.
Map each function to an endpoint
Each path below was called with a live key on 3 November 2026. Look a stock up with /v1/equities/search first, because Narwhal ids carry the exchange, as in XNYS:IBM.
| Alpha Vantage function | Narwhal endpoint | What differs |
|---|---|---|
CURRENCY_EXCHANGE_RATE | GET /v1/fx/rates/{base}?currencies= | Several currencies per call. A rate with a timestamp, no bid or ask. |
FX_DAILY | GET /v1/fx/rates/{base}/observations | One rate per day. For open, high, low and close, call /v1/fx/rates/USD/bars with USD as the base. |
GLOBAL_QUOTE | GET /v1/equities/{id}/price | change_percent carries no percent sign. |
TIME_SERIES_DAILY | GET /v1/equities/{id}/bars?interval=1d | Weekly and monthly bars have no endpoint; aggregate the daily bars. |
SYMBOL_SEARCH | GET /v1/equities/search | Narrow results with country. |
DIGITAL_CURRENCY_DAILY | GET /v1/crypto/{pair}/bars | Pairs read BTC-USD. |
CPI | GET /v1/economics/{country}/cpi/observations | Uses period, not date. |
INFLATION | GET /v1/economics/{country}/inflation/observations | Monthly year-over-year, month-over-month and year-to-date, where Alpha Vantage gives an annual percent. |
UNEMPLOYMENT | GET /v1/economics/{country}/unemployment/observations | The field is rate. |
REAL_GDP | GET /v1/economics/{country}/gdp-growth/observations | Growth rates only. /gdp returns an annualized level, so check its definition before comparing. |
FEDERAL_FUNDS_RATE | GET /v1/economics/USA/central-bank/policy-rate/history | Gives the target range as lower_bound and upper_bound, not the effective rate. |
TREASURY_YIELD | GET /v1/economics/USA/yield-curve/history?maturity=10y | Lowercase maturities such as 10y. |
RETAIL_SALES, DURABLES, NONFARM_PAYROLL | GET /v1/economics/calendar | Read each release's values. Payrolls arrive as a monthly change in thousands. |
GOLD_SILVER_SPOT, WTI, BRENT | GET /v1/commodities/spot/{commodity}/{currency} | Latest price, for example XAU/USD. History sits at /bars. |
INCOME_STATEMENT, BALANCE_SHEET, CASH_FLOW | GET /v1/companies/{company_id}/financials?statement= | Filings data under ids such as usa:0000051143. |
What has no Narwhal equivalent
Keep Alpha Vantage, or another source, for these.
- Technical indicators, 53 functions such as
SMA,RSIandMACD. - Options, both realtime and historical.
NEWS_SENTIMENTandIPO_CALENDAR.- Index breadth:
INDEX_DATAlists 200 or more indices, and Narwhal prices 18.
Migrate three calls
- Set your key Get a free key and keep it in
NARWHAL_API_KEY. Narwhal reads it from theAuthorization: Bearerheader, so removeapikeyfrom every URL. - Swap the CPI call The Narwhal path names the country and returns the latest value. For history, add
/observationswithstartandend, which returns the same index values Alpha Vantage lists.# Ran 2026-11-03: Alpha Vantage 200 OK with the demo key, Narwhal 200 OK both calls # Before: Alpha Vantage, CPI curl "https://www.alphavantage.co/query?function=CPI&interval=monthly&apikey=demo" # After: Narwhal, latest US CPI curl "https://api.narwhalapi.com/v1/economics/USA/cpi" \ -H "Authorization: Bearer $NARWHAL_API_KEY" # After: Narwhal, CPI for July to September curl -G \ --url "https://api.narwhalapi.com/v1/economics/USA/cpi/observations" \ -d start=2026-07 -d end=2026-09 \ -H "Authorization: Bearer $NARWHAL_API_KEY" - Swap the quote and FX calls Narwhal resolves a stock by listing id, and an FX rate by base currency with the targets in
currencies.# Ran 2026-11-03: Alpha Vantage quote 200 OK (demo key), Narwhal quote and FX 200 OK # Before: Alpha Vantage, last price for IBM curl "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=IBM&apikey=demo" # After: Narwhal, same stock (ids look like XNYS:IBM) curl "https://api.narwhalapi.com/v1/equities/XNYS:IBM/price" \ -H "Authorization: Bearer $NARWHAL_API_KEY" # Before: Alpha Vantage, USD to JPY (request taken from its documentation, not run) curl -G \ --url "https://www.alphavantage.co/query" \ -d function=CURRENCY_EXCHANGE_RATE -d from_currency=USD \ -d to_currency=JPY -d apikey=YOUR_ALPHA_VANTAGE_KEY # After: Narwhal, USD to JPY curl "https://api.narwhalapi.com/v1/fx/rates/USD?currencies=JPY" \ -H "Authorization: Bearer $NARWHAL_API_KEY" - Rewrite the parser Fields lose their numbers, and the series becomes an array. The script makes all three Narwhal calls.
# Ran 2026-11-03: 200 OK for all three calls import os import requests session = requests.Session() session.headers["Authorization"] = f"Bearer {os.environ['NARWHAL_API_KEY']}" def get(path, **params): r = session.get("https://api.narwhalapi.com" + path, params=params, timeout=10) r.raise_for_status() return r.json() cpi = get("/v1/economics/USA/cpi") # was function=CPI print(cpi["period"], cpi["value"]) ibm = get("/v1/equities/search", q="IBM", country="USA")["results"][0]["id"] print(ibm, get(f"/v1/equities/{ibm}/price")["price"]) # was GLOBAL_QUOTE fx = get("/v1/fx/rates/USD", currencies="JPY")["rates"][0] # was CURRENCY_EXCHANGE_RATE print(fx["currency"], fx["rate"]) - Compare the output Run both providers on the same inputs. US CPI for 2026-09 is 336.940 on both, and the IBM close of 2 November is 252.51 on both.
How the responses differ
Alpha Vantage nests an FX rate under Realtime Currency Exchange Rate with numbered keys. Narwhal returns a rates array with one object per currency.
| Aspect | Alpha Vantage | Narwhal |
|---|---|---|
| Field names | Numbered, such as 05. price | Plain, such as price |
| Series | Object keyed by date, newest first | Array of observations or bars, oldest first |
| Numbers | Strings | Strings, so parse them as decimals |
| Paging | None; outputsize picks 100 points or all | next_cursor |
| Errors | HTTP 200 with Information or Error Message | An HTTP error status and a body with code |
{
"name": "Consumer Price Index for all Urban Consumers",
"interval": "monthly",
"unit": "index 1982-1984=100",
"data": [
{ "date": "2026-09-01", "value": "336.940" },
{ "date": "2026-08-01", "value": "334.980" }
]
}{
"country": "USA",
"period": "2026-09",
"value": "336.940",
"index_base": "1982-84=100",
"released_on": "2026-10-14"
}{
"Global Quote": {
"01. symbol": "IBM",
"05. price": "252.5100",
"07. latest trading day": "2026-11-02",
"08. previous close": "257.8100",
"10. change percent": "-2.0558%"
}
}{
"id": "XNYS:IBM",
"symbol": "IBM",
"currency": "USD",
"price": "252.51",
"previous_close": "257.81",
"change_percent": "-2.06",
"market_session": "closed",
"timestamp": "2026-11-02T21:00:00Z",
"stale": false
}Handle rate limits
The Alpha Vantage free key allows 25 requests a day. Its premium plans run from 75 to 1,200 requests a minute with no daily cap, starting at $49.99 a month. Narwhal Free allows 30 requests a minute and 5,000 a month. Basic allows 120 a minute and 100,000 a month, and Pro allows 500 and 1,000,000.
Alpha Vantage reports problems inside a 200 response, so a check on the status code misses them; for calls outside its examples, the demo key returned an Information note. Narwhal answers 429. A rate_limit_exceeded code means wait for the Retry-After header and retry, and quota_exhausted means the month is spent until 00:00 UTC on the 1st. Neither counts against your quota. Each success carries X-RateLimit-Remaining and X-RateLimit-Reset. See cache responses and handle 429 errors for caching.
# Ran 2026-11-03: 200 OK on both test calls; the 429 branch follows the documented codes
import os
import time
import requests
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['NARWHAL_API_KEY']}"
def get(path, **params):
for attempt in range(4):
r = session.get("https://api.narwhalapi.com" + path, params=params, timeout=10)
if r.status_code == 429:
if r.json().get("code") == "quota_exhausted":
raise RuntimeError("Monthly quota used up; it resets on the 1st (UTC).")
time.sleep(float(r.headers.get("Retry-After", 2)))
continue
r.raise_for_status()
return r.json()
raise RuntimeError(f"Gave up on {path}")How do I find the id of a stock?
Call /v1/equities/search?q=IBM&country=USA. Each result holds an id such as XNYS:IBM for prices and bars, and a company_id such as usa:0000051143 for financials.
Can I keep Alpha Vantage for the rest?
Yes. Each provider keeps its own key and quota, so move the families in the table and leave indicators, options and sentiment where they are. Narwhal compared with Alpha Vantage lists the other differences.
Migration checklist
- List every
functionyour code calls and mark it against the table. - Resolve stock symbols to listing ids once, and store the ids.
- Move the key to the Bearer header and strip it from logged URLs.
- Rewrite parsers for plain names, oldest-first arrays and string numbers.
- Replace checks for
Informationwith checks on status andcode. - Confirm the definition of GDP and the federal funds rate before comparing numbers.
- Retry on
Retry-Afterand stop onquota_exhausted. - Run both providers side by side and compare values before you switch.
Published .