# How to Query FXMacroData via GraphQL

Canonical: https://fxmacrodata.com/articles/how-to-query-fxmacrodata-via-graphql
Author: FXMacroData
Published: 2026-03-30T08:52:00Z

Batch multiple indicator queries, discover the full data catalogue, and retrieve release calendars in a single HTTP round-trip using the FXMacroData GraphQL endpoint — with Python and JavaScript examples.

By the end of this guide you will be able to query any macroeconomic indicator, discover the full catalogue of available data, and check upcoming release dates — all through the FXMacroData**GraphQL endpoint**— using nothing more than`curl`, Python, or JavaScript. You will also know how to batch multiple queries into a single round-trip so your scripts stay lean and fast.

### Prerequisites

- A**FXMacroData API key**—[USD](/united-states) indicators and the data catalogue are free without a key; all other currencies require one. Get yours at[fxmacrodata.com](https://fxmacrodata.com)

- `curl`(or any HTTP client) for the initial test calls

- Python 3.9+ with the`requests`library (`pip install requests`) — for the Python examples

- Node.js 18+ — for the JavaScript examples

- Basic familiarity with GraphQL query syntax (a field list inside curly braces)

## Why GraphQL instead of REST?

The FXMacroData REST API serves each indicator at its own endpoint — one round-trip per currency/indicator combination. GraphQL lets you declare exactly the fields you need and combine multiple independent queries into a single HTTP request. If you want the[EUR](/eurozone)[inflation](/indicators/inflation) series*and*the[GBP](/united-kingdom)[policy rate](/indicators/policy-rate)*and*the upcoming release calendar for both currencies, that is one POST instead of four GET requests.

The GraphQL surface mirrors the public REST endpoints exactly: the same authentication rules, the same data, and the same field names — just served through a single`POST /api/v1/graphql`endpoint with a JSON body.

GraphQL endpoint at a glance

- **URL:**`https://api.fxmacrodata.com/v1/graphql`

- **Method:**POST

- **Auth:**`?api_key=YOUR_API_KEY`query parameter

- **Content-Type:**`application/json`

- **Free access:**USD indicators and`dataCatalogue`/`calendar`(no key required)

- **Query fields:**`announcements`,`dataCatalogue`,`calendar`

## Step 1 — Send your first GraphQL query

Every GraphQL request is a JSON object with a`query`key whose value is your GraphQL query string. Start with a free USD inflation query — no API key required:

```
curl -s -X POST "https://api.fxmacrodata.com/v1/graphql" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ announcements(currency: \"USD\", indicator: \"inflation\") { currency indicator data { date val pctChange } } }"
  }'
```

The response is standard GraphQL JSON wrapped in a`data`envelope:

```
{
  "data": {
    "announcements": {
      "currency": "USD",
      "indicator": "inflation",
      "data": [
        { "date": "2025-01-01", "val": 3.0, "pctChange": null },
        { "date": "2025-02-01", "val": 2.8, "pctChange": -6.67 },
        { "date": "2025-03-01", "val": 2.4, "pctChange": -14.29 }
      ]
    }
  }
}
```

For any non-USD currency, append your API key as a query parameter on the endpoint URL:

```
https://api.fxmacrodata.com/v1/graphql?api_key=YOUR_API_KEY
```

**Tip:**`pctChange`is the month-over-month (or period-over-period) change relative to the previous data point. The first point in a series always returns`null`because there is no prior value to compare against.

## Step 2 — Discover available indicators with`dataCatalogue`

Before querying a specific indicator you can ask the API what data it has for any currency. The`dataCatalogue`query returns every available indicator slug, its human-readable name, unit, release frequency, and whether the central bank publishes an official forecast for it.

```
curl -s -X POST "https://api.fxmacrodata.com/v1/graphql" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ dataCatalogue(currency: \"EUR\") { currency indicators { slug name unit frequency hasOfficialForecast } } }"
  }'
```

Example response (abbreviated):

```
{
  "data": {
    "dataCatalogue": {
      "currency": "EUR",
      "indicators": [
        { "slug": "inflation",    "name": "Inflation (CPI)", "unit": "%",    "frequency": "monthly",   "hasOfficialForecast": false },
        { "slug": "policy_rate",  "name": "Policy Rate",     "unit": "%",    "frequency": "irregular",  "hasOfficialForecast": true  },
        { "slug": "gdp",          "name": "GDP Growth",      "unit": "%",    "frequency": "quarterly", "hasOfficialForecast": false },
        { "slug": "unemployment", "name": "Unemployment",    "unit": "%",    "frequency": "monthly",   "hasOfficialForecast": false }
      ]
    }
  }
}
```

The`slug`values are the exact strings you pass as the`indicator`argument in subsequent`announcements`queries. You can browse the full indicator catalogue interactively at the[API data docs](/api-data-docs/) .

## Step 3 — Fetch historical data with optional date filters

The`announcements`query accepts optional`startDate`and`endDate`arguments in`YYYY-MM-DD`format. Without them the API returns a sensible default window (typically 12–24 months). You can also request the central bank target alongside the series — useful when comparing the live reading against the official rate target.

```
curl -s -X POST "https://api.fxmacrodata.com/v1/graphql?api_key=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { announcements(currency: \"AUD\", indicator: \"policy_rate\", startDate: \"2024-01-01\") { currency indicator hasOfficialForecast cbTarget { description current { effectiveFrom target } } data { date val announcementDatetime } } }"
  }'
```

Response highlights:

```
{
  "data": {
    "announcements": {
      "currency": "AUD",
      "indicator": "policy_rate",
      "hasOfficialForecast": true,
      "cbTarget": {
        "description": "RBA cash rate target band",
        "current": { "effectiveFrom": "2023-11-07", "target": 4.35 }
      },
      "data": [
        { "date": "2024-02-06", "val": 4.35, "announcementDatetime": 1707199200 },
        { "date": "2024-03-19", "val": 4.35, "announcementDatetime": 1710813600 }
      ]
    }
  }
}
```

`announcementDatetime`is a Unix timestamp (seconds, UTC) of the official publication. You can find field-level documentation for[AUD](/australia) indicators at the[AUD policy rate docs](/api-data-docs/aud/policy_rate) .

## Step 4 — Query the release calendar

The`calendar`query returns the scheduled UTC announcement times for every upcoming indicator release for a given currency. Pass an optional`indicator`argument to narrow the results to a single indicator.

```
curl -s -X POST "https://api.fxmacrodata.com/v1/graphql?api_key=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ calendar(currency: \"GBP\", indicator: \"inflation\") { currency data { release announcementDatetime } } }"
  }'
```

```
{
  "data": {
    "calendar": {
      "currency": "GBP",
      "data": [
        { "release": "inflation", "announcementDatetime": 1745917200 }
      ]
    }
  }
}
```

Convert`announcementDatetime`to a human-readable UTC time in Python with`datetime.utcfromtimestamp(1745917200)`, or in JavaScript with`new Date(1745917200 * 1000).toISOString()`. For the GBP inflation indicator details see the[GBP inflation docs](/api-data-docs/gbp/inflation) .

## Step 5 — Batch multiple queries in one request

GraphQL's biggest practical advantage is the ability to name and send multiple independent queries in a single HTTP POST. Use query aliases to avoid field name conflicts — each alias becomes a separate key in the`data`response object.

```
curl -s -X POST "https://api.fxmacrodata.com/v1/graphql?api_key=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query MultiIndicator { eurInflation: announcements(currency: \"EUR\", indicator: \"inflation\") { currency indicator data { date val } } gbpRate: announcements(currency: \"GBP\", indicator: \"policy_rate\") { currency indicator data { date val } } audCalendar: calendar(currency: \"AUD\") { currency data { release announcementDatetime } } }"
  }'
```

The response carries all three results in one payload:

```
{
  "data": {
    "eurInflation": { "currency": "EUR", "indicator": "inflation", "data": [ ... ] },
    "gbpRate":      { "currency": "GBP", "indicator": "policy_rate", "data": [ ... ] },
    "audCalendar":  { "currency": "AUD", "data": [ ... ] }
  }
}
```

**Tip:**Batching is especially valuable in serverless and edge environments where connection overhead is expensive. One POST replaces three sequential REST calls and the response arrives after a single DNS + TLS handshake.

## Step 6 — Python client

The pattern below wraps GraphQL requests in a small helper so your application code stays readable. It supports single queries and batched alias queries with the same function.

```
import requests

GRAPHQL_URL = "https://api.fxmacrodata.com/v1/graphql"
API_KEY = "YOUR_API_KEY"   # leave empty for free USD/catalogue endpoints

def gql(query: str) -> dict:
    """Send a GraphQL query and return the parsed `data` object."""
    params = {"api_key": API_KEY} if API_KEY else {}
    resp = requests.post(
        GRAPHQL_URL,
        params=params,
        json={"query": query},
        headers={"Content-Type": "application/json"},
        timeout=15,
    )
    resp.raise_for_status()
    payload = resp.json()
    if "errors" in payload:
        raise RuntimeError(f"GraphQL errors: {payload['errors']}")
    return payload["data"]

# ── Discover indicators for AUD ──────────────────────────────────────────────
catalogue = gql('{ dataCatalogue(currency: "AUD") { indicators { slug name frequency } } }')
for ind in catalogue["dataCatalogue"]["indicators"]:
    print(f"  {ind['slug']:25s}  {ind['name']}  ({ind['frequency']})")

# ── Fetch EUR inflation + GBP policy rate in one round-trip ─────────────────
batch = gql('''
query {
  eurInflation: announcements(currency: "EUR", indicator: "inflation") {
    currency indicator data { date val pctChange }
  }
  gbpRate: announcements(currency: "GBP", indicator: "policy_rate") {
    currency indicator data { date val }
  }
}
''')

eur_latest = batch["eurInflation"]["data"][-1]
gbp_latest = batch["gbpRate"]["data"][-1]
print(f"EUR CPI   {eur_latest['date']}: {eur_latest['val']}%  ({eur_latest['pctChange']:+.2f}% MoM)")
print(f"GBP Rate  {gbp_latest['date']}: {gbp_latest['val']}%")

```

## Step 7 — JavaScript / Node.js client

The native`fetch`API (Node.js 18+) handles GraphQL requests with minimal boilerplate. The pattern mirrors the Python helper above.

```
const GRAPHQL_URL = "https://api.fxmacrodata.com/v1/graphql";
const API_KEY = "YOUR_API_KEY"; // set to "" for free USD/catalogue endpoints

async function gql(query) {
  const url = API_KEY ? `${GRAPHQL_URL}?api_key=${API_KEY}` : GRAPHQL_URL;
  const resp = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query }),
  });
  if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
  const payload = await resp.json();
  if (payload.errors) throw new Error(JSON.stringify(payload.errors));
  return payload.data;
}

// Batched query: EUR inflation + calendar
const data = await gql(`
  query {
    eurInflation: announcements(currency: "EUR", indicator: "inflation") {
      data { date val pctChange }
    }
    eurCalendar: calendar(currency: "EUR", indicator: "inflation") {
      data { release announcementDatetime }
    }
  }
`);

const latest = data.eurInflation.data.at(-1);
const nextRelease = data.eurCalendar.data[0];

console.log(`EUR CPI ${latest.date}: ${latest.val}% (${latest.pctChange > 0 ? "+" : ""}${latest.pctChange?.toFixed(2)}% MoM)`);
if (nextRelease) {
  const dt = new Date(nextRelease.announcementDatetime * 1000).toISOString();
  console.log(`Next EUR inflation release: ${dt}`);
}

```

## Step 8 — Handle errors gracefully

GraphQL returns HTTP 200 even when a query field fails. Errors appear in a top-level`errors`array alongside any partial`data`that did succeed. Check for this array before using the response — a failed alias in a batched query will not prevent the other aliases from returning data.

```
payload = resp.json()

# Partial success: some aliases may have data, others may have errors
if "errors" in payload:
    for err in payload["errors"]:
        print(f"[GraphQL error] {err.get('message')} — path: {err.get('path')}")

data = payload.get("data") or {}
if "eurInflation" in data and data["eurInflation"]:
    process(data["eurInflation"])

```

**Common errors to handle:**
- **Unsupported currency**— the`errors`array will contain a message like*"Unsupported currency: XYZ"*. Check your currency code against the[API docs](/api-data-docs/) .

- **Invalid indicator**— run a`dataCatalogue`query first to confirm the indicator slug exists for your target currency.

- **Authentication error**— HTTP 401 or a GraphQL error citing an invalid key. Verify`api_key`is appended to the URL, not the JSON body.

### What you accomplished

- ✓ Sent your first GraphQL query to`https://api.fxmacrodata.com/v1/graphql`

- ✓ Used`dataCatalogue`to discover every available indicator for a currency

- ✓ Fetched filtered historical data using`startDate`and`endDate`arguments

- ✓ Retrieved upcoming release timestamps with the`calendar`query

- ✓ Batched multiple independent queries into a single HTTP POST using named aliases

- ✓ Built reusable GraphQL helper functions in both Python and JavaScript

- ✓ Handled partial errors without discarding valid data from other aliases

## Next steps

Now that you can query the GraphQL endpoint fluently, a few natural extensions will make your integration production-ready:

- **Schedule queries around release times.**Combine the`calendar`query with the scheduling pattern described in[How to Use the Release Calendar API to Schedule Indicator Fetches](/articles/how-to-schedule-with-release-calendar) — wake up just before each announcement and fire your`announcements`query the moment new data is published.

- **Explore the full schema interactively.**If you have access to a dev environment with`ENABLE_GRAPHIQL=true`, open`/api/v1/graphql`in your browser to use the built-in GraphiQL IDE with autocomplete and inline documentation for every field.

- **Extend your coverage to more currencies.**Run`dataCatalogue`for each of the supported currencies — USD, EUR, GBP, AUD,[CAD](/canada) ,[JPY](/japan) ,[CHF](/switzerland) , and[NZD](/new-zealand) — to build a full picture of what data is available across the G8 FX universe.

— The FXMacroData Team

Source: FXMacroData
