Rate limiting

Rate limits ensure fair access and protect system stability for all users.

Default limits#

For self-serve customers:

Window Limit
Per minute 60 requests
Per day 1,000 requests
Enterprise customers have higher limits defined in their subscription agreement. Contact support if you need increased limits.

What happens when you exceed the limit#

The API returns 429 Too Many Requests with two headers:

Header Meaning
Retry-After Seconds to wait before retrying
X-RateLimit-Limit Your limit for the current window

Handling 429s in your code#

Do not immediately retry on a 429. Use exponential backoff — wait progressively longer between retries:

# curl doesn't retry automatically — wrap it in a shell loop
while true; do
  STATUS=$(curl -s -o response.json -w "%{http_code}" \
    -X POST 'https://api.ocean.io/v3/search/companies' \
    -H 'X-Api-Token: YOUR_API_TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{ "size": 50 }')
  [ "$STATUS" != "429" ] && break
  WAIT=$(grep -i "retry-after" response.json | awk '{print $2}' || echo 1)
  sleep "$WAIT"
done
import time
import requests

def request_with_backoff(url, headers, payload, max_retries=5):
    for attempt in range(max_retries):
        response = requests.post(url, headers=headers, json=payload)
        if response.status_code != 429:
            return response
        retry_after = int(response.headers.get("Retry-After", 2**attempt))
        time.sleep(retry_after)
    raise RuntimeError("Rate limit retries exhausted")
async function requestWithBackoff(url, headers, body) {
  while (true) {
    const res = await fetch(url, {
      method: 'POST',
      headers: { ...headers, 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
    });
    if (res.status !== 429) return res;
    const wait = parseInt(res.headers.get('Retry-After') ?? '1', 10);
    await new Promise(r => setTimeout(r, wait * 1000));
  }
}

Tips for staying within limits#

  • Use the size parameter to request only as many results as you need
  • Use the fields parameter to request only the fields you need — this reduces latency and can help with throughput
  • For large batch operations, spread requests over time rather than bursting
  • Check your daily limit balance via the Get Credit Balance endpoint — the dailyLimitRateLeft field shows how many requests remain today