Skip to main content
Marble applies rate limits to protect the stability of the API for all users. This page explains the limits, how they are calculated, and how to design your integration to handle them gracefully.

Overview

Marble API uses rate limiting to ensure fair usage and API stability. Rate limits are enforced per API key using a sliding window approach.
Most applications will not hit these limits during normal use, but you should still build in defensive handling for rate limit responses.

Rate Limit Tiers

API Key Requests

All authenticated requests are rate limited per API key:
  • Limit: 200 requests per 10 seconds
  • Applies to: All resource routes
    • GET /posts
    • GET /posts/:identifier
    • GET /categories
    • GET /tags
    • GET /authors
This means each API key can make up to 200 requests every 10 seconds before receiving 429 Too Many Requests responses.

Unauthenticated Requests

Requests without a valid API key have a more conservative limit:
  • Limit: 10 requests per 10 seconds

Rate Limit Response Headers

When rate limiting is active, responses include standard headers that let you understand how many requests you have remaining in the current window.
X-RateLimit-Limit
integer
The maximum number of requests allowed in the current window.
X-RateLimit-Remaining
integer
The number of requests remaining in the current window before you hit the limit.
X-RateLimit-Reset
integer
Unix timestamp (in seconds) when the current rate limit window resets.
You should use these headers to dynamically adjust your request rate, especially for background jobs and batch operations.

When You Exceed the Limit

If you exceed the allowed number of requests in the current window, the API returns a 429 Too Many Requests error.
curl -i -H "Authorization: Bearer YOUR_API_KEY" "https://api.marblecms.com/v1/posts"
{
  "error": "Too many requests",
  "details": {
    "message": "You have exceeded the allowed number of requests. Please try again after the reset time.",
    "statusCode": 429
  }
}
If you receive 429 responses, you should back off immediately, respect the X-RateLimit-Reset header, and implement exponential backoff with jitter in automated clients.

Implementing Backoff

Here’s a simple example of exponential backoff in 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) {
      const resetTime = response.headers.get("X-RateLimit-Reset");
      const waitMs = resetTime
        ? parseInt(resetTime) * 1000 - Date.now()
        : Math.pow(2, attempt) * 1000;

      await new Promise((resolve) => setTimeout(resolve, waitMs));
      continue;
    }

    return response;
  }
  throw new Error("Max retries exceeded");
}

Best Practices

  • Cache responses: Store API responses where possible to reduce API calls.
  • Batch operations: Process items sequentially with delays rather than parallel requests. - Monitor headers: Track X-RateLimit-Remaining and slow down before hitting limits. - Use webhooks: For real-time updates, consider webhooks instead of polling the API.
If you consistently need higher rate limits for your use case, please contact us to discuss your requirements.