Securely Redirecting...

Connecting to Stripe

How to Query FXMacroData via GraphQL banner image

Builders

Engineering

How to Query FXMacroData via GraphQL

A step-by-step guide to connecting to the FXMacroData GraphQL endpoint — from your first query to batching multiple indicators in a single request — 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 indicators and the data catalogue are free without a key; all other currencies require one. Get yours at 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 inflation series and the GBP 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://fxmacrodata.com/api/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://fxmacrodata.com/api/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://fxmacrodata.com/api/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://fxmacrodata.com/api/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.


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://fxmacrodata.com/api/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 indicators at the AUD policy rate docs.


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://fxmacrodata.com/api/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.


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://fxmacrodata.com/api/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://fxmacrodata.com/api/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://fxmacrodata.com/api/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.
  • 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://fxmacrodata.com/api/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 — 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, JPY, CHF, and NZD — to build a full picture of what data is available across the G8 FX universe.

— The FXMacroData Team