Skip to main content

Rate Limiting

The Geo-Engine API implements rate limiting to ensure fair usage and platform stability.

Understanding Rate Limits

When you exceed your rate limit, the API responds with:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1645000000
X-RateLimit-Retry-After: 60

Response Headers

  • X-RateLimit-Limit - Maximum requests allowed in this window
  • X-RateLimit-Remaining - Requests remaining in current window
  • X-RateLimit-Reset - Unix timestamp when the limit resets
  • X-RateLimit-Retry-After - Seconds to wait before retrying

Checking Your Limits

Every successful response includes rate limit headers. Monitor these to avoid hitting your limit.

JavaScript Example

async function checkRateLimit() {
const response = await fetch('https://graph.quarticle.ro/graph/api/v1/places/geocode?q=Berlin', {
headers: { 'Authorization': `${apiKey}` }
});

console.log('Limit:', response.headers.get('X-RateLimit-Limit'));
console.log('Remaining:', response.headers.get('X-RateLimit-Remaining'));
console.log('Reset:', response.headers.get('X-RateLimit-Reset'));

return response.json();
}

Python Example

import requests
import time

headers = {'Authorization': f'{api_key}'}
response = requests.get('https://graph.quarticle.ro/graph/api/v1/places/geocode?q=Berlin', headers=headers)

print(f"Limit: {response.headers.get('X-RateLimit-Limit')}")
print(f"Remaining: {response.headers.get('X-RateLimit-Remaining')}")
print(f"Reset: {response.headers.get('X-RateLimit-Reset')}")

Best Practices

1. Implement Backoff

Don't immediately retry when hitting the rate limit. Use exponential backoff:

async function apiRequestWithBackoff(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);

if (response.status !== 429) {
return response;
}

const retryAfter = response.headers.get('X-RateLimit-Retry-After') || 60;
console.log(`Rate limited. Retrying after ${retryAfter}s`);

await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
}

throw new Error('Max retries exceeded');
}

2. Cache Results

Cache API responses to reduce redundant requests:

const cache = new Map();
const CACHE_TTL = 60000; // 60 seconds

async function fetchWithCache(url) {
const now = Date.now();

if (cache.has(url)) {
const { data, timestamp } = cache.get(url);
if (now - timestamp < CACHE_TTL) {
return data;
}
}

const response = await fetch(url, {
headers: { 'Authorization': `${apiKey}` }
});
const data = await response.json();

cache.set(url, { data, timestamp: now });
return data;
}

Rate Limit Window

Rate limits are calculated per minute and reset hourly. For example:

  • If your limit is 60 requests/minute
  • You can make up to 60 requests in any 60-second window
  • The window rolls forward continuously (not calendar-based)

Burst Requests

You can exceed your per-minute limit momentarily if you have unused requests from previous minutes. However, you cannot exceed your daily limit.