Most investors track earnings dates the same way: a spreadsheet of tickers, a dozen investor-relations pages bookmarked, and a separate economic calendar site open in another tab, hoping nothing moves before they check again. An earnings calendar API turns that whole routine into two REST calls.
If you’re building:
- a pre-earnings dashboard for a watchlist,
- a macro risk calendar for a portfolio,
- or an alert system for reports and releases that move a position,
the dates, consensus estimates, and surprises already come computed.
Quick jump:
- 1 Checking each source by hand doesn’t scale
- 2 Earnings calendar API and economic events: two cheap endpoints
- 3 The advantage: watching a portfolio instead of one ticker
- 4 What the earnings calendar API fields actually tell you
- 5 Reading the economic events fields
- 6 How to get your EODHD API key
- 7 Using the earnings calendar API for a watchlist
- 8 Pulling economic events by country
- 9 One more example: catching earnings and macro events colliding
- 10 Exporting a quarter of earnings calendar API data to CSV
- 11 Handling earnings calendar API errors
- 12 Things to keep in mind with the earnings calendar API
- 13 Economic events filters, costs and demo limits
- 14 Three things worth remembering
- 15 FAQs
- 16 Final Thoughts
Checking each source by hand doesn’t scale
A single company’s investor-relations page usually has the next earnings date, sometimes. Timing (before or after market) is often missing or buried in a PDF. Multiply that by a twenty-stock watchlist and it’s twenty tabs, twenty different formats, and no consensus estimate to compare against.
Macro events are worse. CPI, GDP, PMI, and central bank releases live across country-specific statistics offices and financial news sites. Each source has its own naming and revision history. None gives you a consistent way to filter by country or compare month-over-month against year-over-year.
Neither problem is about finding a date. It’s about getting the consensus and the outcome in the same place, for many tickers or countries at once.
Earnings calendar API and economic events: two cheap endpoints
EODHD covers this with two separate REST endpoints, the Earnings Calendar API and the Economic Events API, each returning one clean JSON structure instead of a page to scrape:
GET /api/calendar/earnings # who reports when, actual EPS vs consensus, already worked out
GET /api/economic-events # macro releases by country, with actual vs estimate vs previous
Both cost 1 API call per request, whatever the date range or filters. That’s a real contrast with the options endpoints from the previous guide, where a single call already costs 10.
The advantage: watching a portfolio instead of one ticker
Checking earnings dates and macro releases by hand scales to maybe three or four positions before it turns into a part-time job. A screen built on both endpoints removes that ceiling entirely. You can rerun it every morning for the cost of two API calls.
That changes what’s actually practical to check before putting money at risk:
- Sizing a position ahead of a report based on the company’s own multi-year beat/miss record, not a guess or a headline about “whisper numbers.”
- Spotting the one week that stacks several portfolio holdings’ earnings on top of a CPI print or an FOMC decision, the highest-risk week to be full size or unhedged.
- Catching a moved report date or a consensus estimate that shifted, without refreshing a dozen investor-relations pages to notice.
None of this needs a model. It needs the two calendars in the same place, which is what the rest of this guide sets up.
What the earnings calendar API fields actually tell you
On the earnings side, actual and estimate give you the surprise directly: percent is the beat or miss relative to consensus, and difference is the same thing in raw currency. A stock beating by 2% reads very differently from one beating by 20%. Percent makes that comparable across companies with wildly different EPS scales.
Pulled across several years instead of one quarter, that same field turns into a track record. A company that has beaten estimates eight quarters running is a different risk to hold into a report than one that misses as often as it beats. That pattern only shows up when you line up actual and estimate across many reports. Memory of the last earnings call won’t show it.
before_after_market matters more than it looks, and not just for staying awake at the right time. AfterMarket earnings move the stock overnight. The first real reaction shows up as a gap at the next open. A stop order sitting at yesterday’s price can’t protect you from that. BeforeMarket earnings trade live the same day, which leaves room to react intraday instead of waking up to a gap. Knowing which one applies is what tells you whether a hedge needs to cover an overnight gap or an intraday swing.
Reading the economic events fields
On the economic side, the same actual vs estimate logic applies at a country level instead of a company level, but comparison changes what the headline number means. Month-over-month inflation reads very differently from the same release framed year-over-year. A single CPI print can look tame month-over-month and alarming year-over-year, or the other way round, so the comparison field is part of interpreting the number, not just metadata.
The practical use is portfolio-level, not just one release at a time: a week that stacks a CPI print, an FOMC decision, and three holdings reporting earnings carries more risk than a quiet week, whatever any single position looks like on its own. Flagging that combination ahead of time, the way the screener further down does, is a decision input a single-ticker earnings alert never gives you.
How to get your EODHD API key
1. Use the “demo” API key to test our data from a limited set of tickers without registering:
AAPL.US | TSLA.US | VTI.US | AMZN.US | BTC-USD | EUR-USD
Real-Time Data and all of the APIs (except Bulk) are included without API calls limitations with these tickers and the demo key.
2. Register to get your free API key (limited to 20 API calls per day) with access to:
End-Of-Day Historical Data with only the past year for any ticker, and the List of tickers per Exchange.
3. To unlock your API key, we recommend to choose the subscription plan which covers your needs.
For these calendar endpoints the demo key is more limited: /calendar/earnings only accepts AAPL.US and MSFT.US, and /economic-events needs a real API key.
Using the earnings calendar API for a watchlist
The demo token works here too, but only for AAPL.US and MSFT.US; any other symbol returns a 403. For a real watchlist, symbols narrows the window rather than replacing it. You still need to pass from and to:
import requests
API_TOKEN = "YOUR_API_TOKEN"
BASE_URL = "https://eodhd.com/api/calendar/earnings"
params = {
"symbols": "AAPL.US,MSFT.US,NVDA.US",
"from": "2025-01-01",
"to": "2025-12-31",
"api_token": API_TOKEN,
"fmt": "json",
}
resp = requests.get(BASE_URL, params=params)
resp.raise_for_status()
data = resp.json()
for record in data["earnings"]:
surprise = record["percent"] if record["estimate"] is not None else None
print(
f"{record['code']} | reports {record['report_date']} | "
f"{record['before_after_market']} | actual {record['actual']} | "
f"estimate {record['estimate']} | surprise {surprise}"
)
Note the fmt=json parameter. Omit it and the earnings calendar API quietly returns CSV instead. The CSV also uses different column names (Code, Report_Date, BeforeAfterMarket) than the JSON fields above.
Pulling economic events by country
Same shape, different filters. country takes a two-letter ISO code, and type filters to one exact event label. The default limit is 50 records. Set limit=1000, the maximum, and split long date windows when needed:
BASE_URL = "https://eodhd.com/api/economic-events"
params = {
"from": "2025-03-01",
"to": "2025-03-07",
"country": "US",
"limit": 1000, # default: 50 records; maximum: 1000
"api_token": API_TOKEN,
"fmt": "json",
}
resp = requests.get(BASE_URL, params=params)
resp.raise_for_status()
events = resp.json()
for event in events:
print(
f"{event['date']} | {event['country']} | {event['type']} | "
f"actual {event['actual']} vs estimate {event['estimate']} ({event['comparison']})"
)
Filtering to one release type, GDP Growth Rate in this case, works the same way (this endpoint needs a real token, the demo key returns 403), and the same limit applies: this exact query matches 230 events, so set limit=1000 to get all of them:
curl -g "https://eodhd.com/api/economic-events?api_token=YOUR_API_TOKEN&from=2025-01-01&to=2025-03-31&type=GDP%20Growth%20Rate&limit=1000&fmt=json"
One more example: catching earnings and macro events colliding
This is the use case unique to combining both endpoints: a stock reporting earnings the same week as a high-impact macro release trades differently than one reporting in a quiet week. Cross-referencing the two calendars for a watchlist surfaces that overlap automatically.
from datetime import date, timedelta
WATCHLIST = ["AAPL.US", "MSFT.US", "NVDA.US"]
today = date.today()
window_end = today + timedelta(days=14)
earnings_resp = requests.get(
"https://eodhd.com/api/calendar/earnings",
params={
"symbols": ",".join(WATCHLIST),
"from": today.isoformat(),
"to": window_end.isoformat(),
"api_token": API_TOKEN,
"fmt": "json",
},
)
earnings_resp.raise_for_status()
upcoming = earnings_resp.json().get("earnings", [])
events_resp = requests.get(
"https://eodhd.com/api/economic-events",
params={
"from": today.isoformat(),
"to": window_end.isoformat(),
"country": "US",
"limit": 1000, # a 14-day US window can easily exceed the default 50
"api_token": API_TOKEN,
"fmt": "json",
},
)
events_resp.raise_for_status()
macro_events = events_resp.json()
for report in upcoming:
same_day = [e["type"] for e in macro_events if e["date"].startswith(report["report_date"])]
if same_day:
print(f"{report['code']} reports {report['report_date']}, same day as: {', '.join(same_day)}")
Exporting a quarter of earnings calendar API data to CSV
For a one-off analysis in a spreadsheet rather than a script, flatten the response into a pandas DataFrame:
import pandas as pd
resp = requests.get(
"https://eodhd.com/api/calendar/earnings",
params={
"from": "2025-01-01",
"to": "2025-03-31",
"api_token": API_TOKEN,
"fmt": "json",
},
)
resp.raise_for_status()
df = pd.DataFrame(resp.json()["earnings"])
df.to_csv("q1_2025_earnings.csv", index=False)
print(f"Saved {len(df)} reports to q1_2025_earnings.csv")
Handling earnings calendar API errors
A small wrapper that turns HTTP errors into clear messages:
def fetch_earnings(symbols, from_date, to_date):
params = {
"symbols": symbols,
"from": from_date,
"to": to_date,
"api_token": API_TOKEN,
"fmt": "json",
}
resp = requests.get("https://eodhd.com/api/calendar/earnings", params=params)
if resp.status_code == 404:
raise ValueError(f"Symbol not found: {symbols}")
if resp.status_code >= 500:
raise RuntimeError("Server error, please retry later")
resp.raise_for_status()
return resp.json()
Things to keep in mind with the earnings calendar API
- Both endpoints default to CSV, not JSON. Always pass fmt=json explicitly, or the response comes back in a different shape with different field names entirely.
- On /calendar/earnings, symbols narrows the date window, it doesn’t replace it. Skip from and to and the window defaults to today through today+7 days. A single-ticker request with no dates usually comes back empty.
- difference is 0, not null, whenever there’s no consensus estimate yet. Check estimate for null before treating a difference of 0 as a real, no-surprise report.
- If a symbol isn’t recognized, check that the ticker exists and uses the SYMBOL.EXCHANGE format (e.g. AAPL.US).
- /calendar/earnings returns the whole window in one response, so pull long histories in quarterly windows or filter by symbols.
Economic events filters, costs and demo limits
- The economic events type filter needs an exact label match, URL-encoded (GDP%20Growth%20Rate). A close-but-not-exact label returns an empty list, not an error.
- /economic-events returns 50 records by default. Set limit=1000, the maximum, and split long date windows into smaller ones.
- Both endpoints cost 1 API call per request, whatever the window size. That’s a real contrast with the options endpoints from the previous guide.
- The demo token is more restrictive here than on the options endpoints: /calendar/earnings accepts only AAPL.US and MSFT.US, and /economic-events is blocked entirely, with unsupported demo requests returning HTTP 403 rather than an empty result. Testing with any other symbol, or the error handling in the wrapper above, needs a real token.
Three things worth remembering
- The value of an earnings calendar API isn’t the date, it’s the consensus estimate and the computed surprise sitting next to it.
- before_after_market and comparison aren’t cosmetic fields. They change how you’d actually read the number that follows.
- Cross-referencing both calendars catches a pattern neither one shows alone: a report landing in a week already loaded with macro risk.
FAQs
❓ Is there a free earnings calendar API?
✅ EODHD’s calendar and economic events data ship under the Fundamentals Data Feed and All-In-One plans, or as a standalone Corporate Events Calendar & News Feed product. The demo token is limited for testing: on /calendar/earnings it only accepts AAPL.US and MSFT.US, and it’s blocked entirely on /economic-events, both returning a 403 rather than sample data.
❓ How far back does earnings history go?
✅ Back to the 1990s for /calendar/earnings. For long historical pulls, use quarterly windows or filter by symbols.
❓ Can I filter economic events by country?
✅ Yes, with a two-letter ISO 3166 code (US, GB, JP, and so on). Combine it with comparison (mom, qoq, yoy) and type to narrow to one kind of release.
❓ What does before_after_market tell me?
✅ Whether the company reported before the market opened or after it closed that day. It’s null when EODHD doesn’t know the timing yet, which happens for reports still far out on the calendar.
❓ Is there a Python SDK for these endpoints?
✅ The official eodhd SDK covers earnings and economic events. The examples here use requests directly against the REST endpoints.
Final Thoughts
A calendar of dates was never the hard part. The consensus estimate sitting next to the actual number is.
Now both arrive in the same response.