API Documentation
Integrate exchange holiday calendars into your ETRM system via our REST API. Available formats include JSON, CSV, and XML (Endur-compatible).
Base URL: https://api.excaltracker.io/v1
All endpoints return data over HTTPS. HTTP requests are redirected.
Authentication
All API requests require an API key passed in the X-API-Key header. You can generate and manage API keys in your portal dashboard.
curl -H "X-API-Key: your_api_key_here" \
https://api.excaltracker.io/v1/exchangesRequests without a valid API key receive a 401 Unauthorized response. Free-tier keys are limited to 100 requests/hour.
List Exchanges
/v1/exchangesReturns all supported exchanges with metadata including region, timezone, and available years.
Response
{
"exchanges": [
{
"code": "ICE_EU",
"name": "ICE Futures Europe",
"region": "EU",
"timezone": "Europe/London",
"website": "https://www.ice.com",
"supported_years": [2025, 2026, 2027],
"products": ["Brent Crude", "Gas Oil", "UK Natural Gas"],
"active": true
},
{
"code": "CME",
"name": "CME Group / NYMEX",
"region": "US",
"timezone": "America/Chicago",
"website": "https://www.cmegroup.com",
"supported_years": [2025, 2026, 2027],
"products": ["WTI Crude", "Henry Hub Natural Gas", "RBOB Gasoline"],
"active": true
}
],
"count": 7,
"last_updated": "2026-03-15T08:00:00Z"
}Get Calendar
/v1/calendars/:exchange/:yearReturns the holiday calendar for a specific exchange and year.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
exchange | string | Exchange code (e.g., ICE_EU, CME, EEX, LME) |
year | integer | Calendar year (2025–2027) |
Query Parameters
| Parameter | Default | Description |
|---|---|---|
format | json | Response format: json, csv, or xml |
Example Response (JSON)
{
"exchange": "ICE_EU",
"exchange_name": "ICE Futures Europe",
"year": 2026,
"generated_at": "2026-03-15T08:00:00Z",
"entry_count": 10,
"entries": [
{
"date": "2026-01-01",
"day_of_week": "Thursday",
"holiday_name": "New Year's Day",
"type": "FULL_CLOSE",
"markets_affected": ["All"],
"trading_hours": null,
"notes": null
},
{
"date": "2026-04-03",
"day_of_week": "Friday",
"holiday_name": "Good Friday",
"type": "FULL_CLOSE",
"markets_affected": ["All"],
"trading_hours": null,
"notes": null
},
{
"date": "2026-12-24",
"day_of_week": "Thursday",
"holiday_name": "Christmas Eve",
"type": "EARLY_CLOSE",
"markets_affected": ["All"],
"trading_hours": "08:00-12:30",
"notes": "Early close at 12:30 GMT"
}
]
}Example Response (CSV)
date,day_of_week,holiday_name,type,markets_affected,trading_hours,notes
2026-01-01,Thursday,New Year's Day,FULL_CLOSE,All,,
2026-04-03,Friday,Good Friday,FULL_CLOSE,All,,
2026-12-24,Thursday,Christmas Eve,EARLY_CLOSE,All,08:00-12:30,Early close at 12:30 GMTResponse Formats
Calendar data is available in three formats, optimized for different integration scenarios:
JSON (default)
Best for programmatic integration. Used by most REST API consumers and custom scripts.
CSV
Compatible with Allegro ETRM import and spreadsheet tools. Includes header row with column names.
XML
Compatible with Endur/OpenLink ETRM import. Schema follows Endur holiday calendar XML specification.
Webhooks
Get notified when calendar data changes. Configure webhook endpoints in your portal dashboard.
Events
| Event | Description |
|---|---|
calendar.updated | A holiday was added, modified, or removed |
calendar.published | New calendar year published for an exchange |
exchange.added | New exchange added to ExCalTracker |
Payload
POST https://your-server.com/webhooks/excaltracker
Content-Type: application/json
X-ExCalTracker-Signature: sha256=a1b2c3d4...
{
"event": "calendar.updated",
"timestamp": "2026-03-15T08:00:00Z",
"data": {
"exchange": "ICE_EU",
"year": 2026,
"change_type": "holiday_added",
"holiday": {
"date": "2026-06-01",
"holiday_name": "Spring Bank Holiday",
"type": "FULL_CLOSE"
}
}
}Signature Verification
Verify webhook authenticity using HMAC-SHA256. The signature is sent in the X-ExCalTracker-Signature header.
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)Rate Limits
Rate limits vary by plan. Exceeding the limit returns 429 Too Many Requests with a Retry-After header.
| Plan | Requests/Hour | Burst |
|---|---|---|
| Starter (Free) | 100 | 10/min |
| Professional | 500 | 50/min |
| Enterprise | 2,000 | 200/min |
Error Handling
The API uses standard HTTP status codes. Error responses include a JSON body with details.
| Code | Description |
|---|---|
400 | Invalid parameters (bad year, unsupported format) |
401 | Missing or invalid API key |
404 | Exchange or year not found |
429 | Rate limit exceeded |
500 | Internal server error |
{
"error": {
"code": "EXCHANGE_NOT_FOUND",
"message": "Exchange 'INVALID' not found. Valid codes: ICE_EU, ICE_US, CME, EEX, LME, TOCOM, SGX",
"status": 404
}
}Code Examples
cURL
# List all exchanges
curl -H "X-API-Key: your_api_key" \
https://api.excaltracker.io/v1/exchanges
# Get ICE Europe 2026 calendar as JSON
curl -H "X-API-Key: your_api_key" \
https://api.excaltracker.io/v1/calendars/ICE_EU/2026
# Get CME calendar as CSV
curl -H "X-API-Key: your_api_key" \
"https://api.excaltracker.io/v1/calendars/CME/2026?format=csv" \
-o cme_2026.csv
# Get EEX calendar as Endur XML
curl -H "X-API-Key: your_api_key" \
"https://api.excaltracker.io/v1/calendars/EEX/2026?format=xml" \
-o eex_2026.xmlPython
import requests
API_KEY = "your_api_key"
BASE_URL = "https://api.excaltracker.io/v1"
headers = {"X-API-Key": API_KEY}
# List exchanges
exchanges = requests.get(f"{BASE_URL}/exchanges", headers=headers).json()
for ex in exchanges["exchanges"]:
print(f"{ex['code']}: {ex['name']} ({ex['region']})")
# Get calendar data
resp = requests.get(
f"{BASE_URL}/calendars/ICE_EU/2026",
headers=headers,
params={"format": "json"}
)
calendar = resp.json()
for entry in calendar["entries"]:
print(f"{entry['date']} - {entry['holiday_name']} ({entry['type']})")JavaScript / Node.js
const API_KEY = "your_api_key";
const BASE_URL = "https://api.excaltracker.io/v1";
// List exchanges
const exchangesRes = await fetch(`${BASE_URL}/exchanges`, {
headers: { "X-API-Key": API_KEY },
});
const { exchanges } = await exchangesRes.json();
exchanges.forEach((ex) => console.log(`${ex.code}: ${ex.name}`));
// Get calendar as JSON
const calendarRes = await fetch(
`${BASE_URL}/calendars/CME/2026?format=json`,
{ headers: { "X-API-Key": API_KEY } }
);
const calendar = await calendarRes.json();
calendar.entries.forEach((entry) => {
console.log(`${entry.date} - ${entry.holiday_name}`);
});Ready to integrate?
Get your free API key and start pulling exchange holiday data in minutes.