Skip to main content

Rate Limits

sunor enforces rate limits to ensure fair usage and platform stability. Limits are applied per API key.

Limits

Endpoint TypeLimitDescription
Task creation60 requests / minutePOST /api/v1/task
Task queries120 requests / minuteGET /api/v1/task/{taskId}
Account endpoints120 requests / minuteGET /api/v1/account/*

Rate limit headers

Every API response includes rate limit information in the headers:
HeaderDescription
X-RateLimit-LimitMaximum number of requests allowed in the current window
X-RateLimit-RemainingNumber of requests remaining in the current window
X-RateLimit-ResetUnix timestamp (seconds) when the rate limit window resets

Example response headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312260

When you hit the limit

If you exceed the rate limit, the API returns a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait.
{
  "code": 429,
  "message": "Rate limit exceeded. Try again in 30 seconds."
}

Response headers on 429

HeaderDescription
Retry-AfterNumber of seconds to wait before retrying

Best practices

Respect Retry-After

When you receive a 429 response, wait for the duration specified in the Retry-After header before making another request.

Use exponential backoff

For automated systems, implement exponential backoff when receiving rate limit errors to avoid hammering the API.

Batch wisely

Instead of submitting many tasks simultaneously, spread submissions over time to stay within limits.

Monitor remaining quota

Check X-RateLimit-Remaining in response headers to proactively slow down before hitting the limit.

Example: rate-limit-aware polling

import time
import requests

def poll_with_rate_limit(api_key, task_id, interval=5):
    while True:
        response = requests.get(
            f"https://sunor.cc/api/v1/task/{task_id}",
            headers={"x-api-key": api_key},
        )

        # Check rate limit headers
        remaining = int(response.headers.get("X-RateLimit-Remaining", 1))
        if remaining < 5:
            print("Approaching rate limit, slowing down...")
            interval = max(interval, 10)

        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 30))
            print(f"Rate limited. Waiting {retry_after}s...")
            time.sleep(retry_after)
            continue

        data = response.json()["data"]
        if data["status"] in ("success", "failure", "timeout"):
            return data

        time.sleep(interval)