Use the Narwhal API in Excel

You can use Excel Power Query and Narwhal to pull holidays, release dates, economics, commodity spot prices, FX rates and prediction-market odds into a workbook. Your Narwhal account and API key work across these data APIs, and Excel can refresh the queries while the workbook is open.

What you'll set up

Power Query is Excel's route for sending the API request and reading its JSON response. You'll end up with queries for the data you want in your workbook, such as a holiday table or a Brent spot price. Each area is its own query in practice. The examples use the same base URL and Authorization header throughout, with a different path and response field for each area. Narwhal also uses the same account for its economics data on CPI, inflation, GDP and yields.

Set your API key

  1. Create a free key Create your free key at Narwhal signup. One account and one API key cover the data APIs used here. REST and MCP share that key; the Excel examples send it with the REST request.
  2. Keep your key in an environment variable Store the key in an environment variable called NARWHAL_API_KEY. In the Power Query M examples, replace YOUR_KEY with your key in the Authorization header. The header value starts with Bearer , followed by the key.
  3. Keep the workbook private Power Query stores the key inside the workbook because the Authorization header sits in the M code. Use a free key for sheets and do not share the file. The environment variable does not replace the key value inside these examples.

Open a blank Power Query

  1. Open Get Data Start on the Data tab and open Get Data. Look for From Other Sources, then Blank Query. These are the Power Query controls used to start the request.
  2. Open the Advanced Editor Open the blank query in the Advanced Editor and paste the M code from the following section. Put your key in the header before refreshing the query.
  3. Select the result to return The expression after in selects the result for that query. The complete example returns Holidays. Return Releases, Cpi, Fx or Fed for those tables, or Brent for the spot price. Use a separate query for each area you want.

Pull data with Power Query M

Keep https://api.narwhalapi.com fixed in Web.Contents. Put the endpoint path in RelativePath and its parameters in Query; this keeps refresh working. The Narwhal helper reads the JSON response, and each expression selects the field for that area. The release-date expression names its output columns and uses MissingField.UseNull.

The helper accepts a path and an optional record of query parameters. When no query record is supplied, it uses an empty record. Table.FromRecords returns tables for the record collections, while Number.FromText handles the Brent price. Leave the response field selection attached to the call for the area you want.

Power Query M for all six areas
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ])),
    Holidays = Table.FromRecords(Narwhal("v1/calendars/holidays/USA/2026")[holidays]),
    Releases = Table.FromRecords(
        Narwhal("v1/economics/calendar", [countries = "USA", start_date = "2026-11-01", end_date = "2026-11-30", limit = "100"])[releases],
        {"at", "period", "topic", "status"}, MissingField.UseNull),
    Cpi = Table.FromRecords(Narwhal("v1/economics/USA/cpi/observations", [start = "2025-09"])[observations]),
    Brent = Number.FromText(Narwhal("v1/commodities/spot/BRENT/USD")[price]),
    Fx = Table.FromRecords(Narwhal("v1/fx/rates/USD", [currencies = "EUR,IDR"])[rates]),
    Fed = Table.FromRecords(Narwhal("v1/predictions/policy-paths/federal-reserve")[meetings])
in
    Holidays  // return Releases, Cpi, Fx or Fed the same way; each area is its own query in practice

Refresh the workbook on a schedule

Use Refresh All on the Data tab to refresh the queries. In query properties, set a query to refresh when the file opens and every N minutes while it is open. Those settings apply to the open workbook, so keep the workbook open for its interval refresh.

Excel has no background scheduler. For an unattended run, use Power Automate or a script outside Excel. A query set to refresh on open can pull data when you open the file again; an interval refresh depends on the workbook remaining open. Set the refresh properties for the queries whose data you want to refresh.

Holidays in Excel

Read USA holidays for 2026 from the holidays field. Each holiday has a date and name, and Table.FromRecords turns the records into a table. This sample returns the holiday table directly, with the same helper and header as the complete example. Replace the key before using it as its own query.

USA holiday table
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ]))
in Table.FromRecords(Narwhal("v1/calendars/holidays/USA/2026")[holidays])

Release dates in Excel

Pull USA economic release dates for November 2026 from releases. The returned fields are at, period, topic and status. Keep the country and date parameters in the Query record. This request is for the release calendar; use the economics query for CPI observation periods and values.

USA release calendar
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ]))
in Table.FromRecords(Narwhal("v1/economics/calendar", [countries = "USA", start_date = "2026-11-01", end_date = "2026-11-30", limit = "100"])[releases], {"at", "period", "topic", "status"}, MissingField.UseNull)

Economics in Excel

Request USA CPI observations with a September 2025 start parameter. Read observations to get the period and value fields in a table. The period belongs with the observation value when you use the result in your workbook. Keep the start parameter in Query, as in the complete example.

USA CPI observations
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ]))
in Table.FromRecords(Narwhal("v1/economics/USA/cpi/observations", [start = "2025-09"])[observations])

Commodity spot prices in Excel

Read the Brent spot price in USD from price. This response field is a price, and the M expression uses Number.FromText to return it as a number. Commodity spot codes include, for example, XAU, XAG, XPT, XPD, XCU, BRENT and WTI. This sample uses BRENT.

Brent spot price in USD
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ]))
in Number.FromText(Narwhal("v1/commodities/spot/BRENT/USD")[price])

Exchange rates in Excel

Use USD as the base currency and request EUR and IDR in the currencies parameter. Select rates from the response and turn the records into a table. Each record has currency and rate, so the returned currency stays alongside its rate in the query result.

USD exchange rates
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ]))
in Table.FromRecords(Narwhal("v1/fx/rates/USD", [currencies = "EUR,IDR"])[rates])

Prediction-market odds in Excel

Pull the Federal Reserve policy path and read meetings from the response. Each meeting has resolves_at, p_cut, p_hold and p_hike. The sample returns the meetings as a table, with the resolution time and policy probabilities available as fields. Use this as its own query when you want these odds in the workbook.

Federal Reserve policy path
let
    Narwhal = (path as text, optional query as record) =>
        Json.Document(Web.Contents("https://api.narwhalapi.com", [
            RelativePath = path,
            Query = if query = null then [] else query,
            Headers = [Authorization = "Bearer YOUR_KEY"]
        ]))
in Table.FromRecords(Narwhal("v1/predictions/policy-paths/federal-reserve")[meetings])

Why does Power Query ask for credentials?

Choose Anonymous authentication for the web source. Power Query allows the Authorization header only with Anonymous authentication. The request still sends your Narwhal key in the header from the M code; the web-source credential choice is Anonymous.

Can I use NETWORKDAYS with the result?

Yes. Point the holiday argument in NETWORKDAYS at the date column of the Holidays table. Use the holiday dates returned by the query for that argument; the name column contains the holiday names. The USA holiday example requests 2026, so its dates are the holidays for that year. Use that result for calculations that need those holiday dates.

Published .