UnmarkdownDocs

Rate Limits

Understand Unmarkdown API rate limits, response headers, and best practices for handling 429 responses.

Rate Limit Tiers

Rate limits are applied per API key on a per-second basis. The limit depends on your plan.

  • Free plan: 10 requests per second
  • Pro plan: 30 requests per second

Requests that exceed the rate limit receive a 429 Too Many Requests response. The response includes headers indicating when you can retry.

Rate Limit Headers

Every API response includes rate limit headers so you can monitor your usage and avoid hitting the limit.

X-RateLimit-Limit

The maximum number of requests allowed per second for your plan.

X-RateLimit-Remaining

The number of requests remaining in the current one-second window.

X-RateLimit-Reset

The Unix timestamp (in seconds) when the current rate limit window resets.

text
HTTP/1.1 200 OK
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27
X-RateLimit-Reset: 1709251200

429 Responses

When you exceed the rate limit, the API returns a 429 Too Many Requests status code with a JSON error body. The Retry-After header indicates how many seconds to wait before retrying.

json
HTTP/1.1 429 Too Many Requests
Retry-After: 1

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after 1 second."
  }
}

Retry Strategy

The recommended approach for handling rate limits is exponential backoff with jitter. Start with a short delay and double it on each consecutive 429 response, adding a small random component to avoid thundering herd problems.

  • First retry: wait 1 second
  • Second retry: wait 2 seconds
  • Third retry: wait 4 seconds
  • Add random jitter of 0 to 500 milliseconds to each wait
  • Cap the maximum backoff at 30 seconds

Retry Example (JavaScript)

javascript
async function fetchWithRetry(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("Retry-After");
    const delay = retryAfter
      ? parseInt(retryAfter) * 1000
      : Math.min(1000 * Math.pow(2, attempt), 30000);
    const jitter = Math.random() * 500;

    await new Promise((r) => setTimeout(r, delay + jitter));
  }
  throw new Error("Max retries exceeded");
}

Retry Example (Python)

python
import time, random, requests

def fetch_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries + 1):
        response = requests.get(url, headers=headers)

        if response.status_code != 429:
            return response

        retry_after = response.headers.get("Retry-After")
        delay = (
            int(retry_after)
            if retry_after
            else min(2**attempt, 30)
        )
        jitter = random.uniform(0, 0.5)
        time.sleep(delay + jitter)

    raise Exception("Max retries exceeded")

Best Practices

Follow these guidelines to stay within your rate limits and build a reliable integration.

  • Monitor the X-RateLimit-Remaining header and throttle requests as it approaches zero
  • Batch operations where possible instead of making many individual requests
  • Implement retry logic with exponential backoff for all API calls
  • Use webhooks or polling intervals rather than tight loops for status checks
  • Upgrade to Pro if you consistently need more than 10 requests per second
Tip
If your application needs to make bursts of requests, spread them over a few seconds rather than sending them all at once. A simple queue with a delay between requests is often enough to stay under the limit.