Skip to main content

Rate Limit Overview

The Exchange Rates API uses a monthly quota system with different limits based on your subscription plan. Rate limits ensure fair usage and optimal performance for all users.
All rate limits are calculated based on your billing cycle and reset on your monthly renewal date.

Plan Comparison

Plan Tiers

PlanPrice (AUD/month)Monthly RequestsHistorical DataTimeseries Max RangeSupport
Free$0300NoneNo accessCommunity
Starter$295,000Last 30 days7 daysEmail (48h)
Professional$7950,000Full (2018+)90 daysEmail (24h)
Business$299500,000Full (2018+)365 daysPhone (4h)

Free Tier Details

The free tier is perfect for:
  • Testing and development
  • Personal projects
  • Small applications with low traffic
  • Proof of concept implementations
Limitations:
  • 300 requests per month
  • No historical data access
  • No timeseries endpoint access
  • Community support only
  • No SLA guarantees
All paid plans include:
  • Higher monthly quotas
  • Historical data access
  • Priority support
  • 99.9% uptime SLA
  • Advanced features (webhooks, CSV exports)*
*Some features coming soon

Rate Limit Headers

Every API response includes rate limit information in the headers:
curl -i https://api.exchangeratesapi.com.au/latest \
  -H "Authorization: Bearer your_api_key_here"
HTTP/2 200
X-RateLimit-Limit-Monthly: 5000
X-RateLimit-Remaining-Monthly: 4847
X-RateLimit-Reset: 2025-10-01T00:00:00Z
X-Request-Id: 123e4567-e89b-12d3-a456-426614174000
HeaderDescription
X-RateLimit-Limit-MonthlyTotal monthly quota for your plan
X-RateLimit-Remaining-MonthlyRemaining requests this month
X-RateLimit-ResetWhen the quota resets (next billing cycle)
X-Request-IdUnique identifier for debugging

Free Endpoint Rate Limits

Some endpoints don’t require authentication but have IP-based rate limits:
EndpointLimitReset Period
GET /statusUnlimited-
GET /symbolsUnlimited-
GET /convert (free)3 requestsPer hour per IP

Free Conversion Example

# No API key required, but limited to 3/hour per IP
curl "https://api.exchangeratesapi.com.au/convert?from=AUD&to=USD&amount=100"
Response includes rate limit headers:
X-RateLimit-Limit: 3
X-RateLimit-Remaining: 2
X-RateLimit-Window: 3600

Rate Limit Exceeded Responses

Monthly Quota Exceeded (Authenticated)

{
  "success": false,
  "error": {
    "code": 429,
    "type": "rate_limit_exceeded",
    "info": "Monthly quota of 5000 requests exceeded. Quota resets on your next billing cycle."
  }
}

IP Rate Limit Exceeded (Free Endpoints)

{
  "success": false,
  "error": {
    "code": 429,
    "type": "rate_limit_exceeded",
    "info": "Rate limit exceeded. Try again in 3456 seconds."
  }
}

Monitoring Your Usage

Dashboard Analytics

Track your API usage in the dashboard:
  • Monthly Usage: Requests made this billing cycle
  • Historical Usage: 12-month usage chart
  • Top Endpoints: Most frequently used endpoints
  • Response Times: Average API performance
  • Error Rates: Success vs error rates

Rate Limit Best Practices

1. Implement Client-Side Throttling

class ExchangeRatesAPI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseURL = 'https://api.exchangeratesapi.com.au';
    this.remainingRequests = null;
    this.quotaResetTime = null;
  }
  
  async makeRequest(endpoint) {
    // Check if we have quota remaining
    if (this.remainingRequests !== null && this.remainingRequests <= 0) {
      const now = new Date();
      if (now < new Date(this.quotaResetTime)) {
        throw new Error('Monthly quota exceeded. Try again after your billing cycle resets.');
      }
    }
    
    const response = await fetch(`${this.baseURL}${endpoint}`, {
      headers: { 'Authorization': `Bearer ${this.apiKey}` }
    });
    
    // Update rate limit info from headers
    this.remainingRequests = parseInt(
      response.headers.get('X-RateLimit-Remaining-Monthly')
    );
    this.quotaResetTime = response.headers.get('X-RateLimit-Reset');
    
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.error.info);
    }
    
    return response.json();
  }
}

2. Cache Responses Intelligently

RBA data updates once daily at 4 PM AEST, so cache aggressively to minimize monthly quota usage:
class CachedExchangeRates {
  constructor(apiKey) {
    this.api = new ExchangeRatesAPI(apiKey);
    this.cache = new Map();
    this.cacheExpiry = new Map();
  }
  
  async getLatestRates() {
    const cacheKey = 'latest';
    const now = Date.now();
    
    // Check if cached data is still fresh
    if (this.cache.has(cacheKey) && 
        this.cacheExpiry.get(cacheKey) > now) {
      return this.cache.get(cacheKey);
    }
    
    // Fetch fresh data
    const data = await this.api.makeRequest('/latest');
    
    // Cache until next RBA update (4 PM AEST next day)
    const tomorrow4PM = new Date();
    tomorrow4PM.setDate(tomorrow4PM.getDate() + 1);
    tomorrow4PM.setHours(16, 0, 0, 0); // 4 PM
    
    this.cache.set(cacheKey, data);
    this.cacheExpiry.set(cacheKey, tomorrow4PM.getTime());
    
    return data;
  }
}

3. Handle Rate Limit Errors Gracefully

async function robustApiCall(apiClient, endpoint) {
  try {
    return await apiClient.makeRequest(endpoint);
  } catch (error) {
    if (error.message.includes('quota exceeded')) {
      // Log the issue and return cached data if available
      console.warn('Monthly API quota exceeded, using cached data');
      return getCachedData(endpoint);
    }
    
    if (error.message.includes('rate limit')) {
      // Wait and retry for temporary rate limits
      await sleep(60000); // Wait 1 minute
      return apiClient.makeRequest(endpoint);
    }
    
    throw error; // Re-throw other errors
  }
}

4. Batch Requests Efficiently

Instead of multiple single-currency requests, use batch endpoints:
// Bad - Multiple requests
const usdRate = await api.makeRequest('/latest/USD');    // 1 request
const eurRate = await api.makeRequest('/latest/EUR');    // 1 request  
const gbpRate = await api.makeRequest('/latest/GBP');    // 1 request
// Total: 3 requests

// Good - Single batch request
const allRates = await api.makeRequest('/latest');       // 1 request
const usdRate = allRates.rates.USD;
const eurRate = allRates.rates.EUR;
const gbpRate = allRates.rates.GBP;
// Total: 1 request

Upgrade Options

When to Upgrade

Consider upgrading when you:
  • Consistently hit monthly quotas
  • Need historical data access
  • Require faster support response
  • Want SLA guarantees
  • Need advanced features

Upgrade Process

1

Choose Plan

Compare plans on our pricing page
2

Upgrade in Dashboard

Visit your dashboard and click “Upgrade”
3

Immediate Effect

New quotas take effect immediately after payment
4

No Code Changes

Your existing API keys continue working with higher limits