Rate Limits

3 min read

WittyForm enforces rate limits on all API requests to ensure fair usage and platform stability. Limits are applied per API key and vary by plan.

Limits by plan

PlanRate limitBurst
FreeNo API access (upgrade to Pro to use the API)
Pro1,000 requests / minute
Enterprise5,000 requests / minute

Limits are measured in fixed 60 second windows, per API key. If you exceed the limit, subsequent requests return 429 Too Many Requests until the window resets.

Rate limit headers

Every API response includes headers that tell you your current rate limit status:

HeaderDescriptionExample
X-RateLimit-LimitYour rate limit ceiling for the current window1000
X-RateLimit-RemainingRequests remaining in the current window847
X-RateLimit-ResetUnix timestamp when the window resets1726412400
X-Request-IdUnique identifier for the request (handy when contacting support)req_8f3a1c2d

Reading headers in code

const response = await fetch('https://wittyform.com/api/v1/forms', {
  headers: { 'Authorization': 'Bearer wf_live_abc123' },
});

const remaining = response.headers.get('X-RateLimit-Remaining');
const resetAt = new Date(
  parseInt(response.headers.get('X-RateLimit-Reset')) * 1000
);

console.log(`${remaining} requests remaining. Resets at ${resetAt.toISOString()}`);

Monitor your usage

GET /api/v1/usage

Rather than tracking the per-response headers yourself, you can ask the API for the calling key's own usage. Any active key may read its own usage (no specific scope is required). The response includes the key's per-minute rate limit plus a daily breakdown of request and error counts, so you can watch volume, spot a broken integration, and detect a leaked key.

Query parameters

ParameterTypeDefaultDescription
daysinteger30How many days of history to return (1 to 90)

Example request

curl -X GET "https://wittyform.com/api/v1/usage?days=7" \
  -H "Authorization: Bearer wf_live_abc123"

Example response

The daily array is ordered newest day first. total_requests and total_errors are summed over the requested window.

{
  "success": true,
  "data": {
    "key_id": "8c1f2d3e-4a5b-4c6d-9e0f-112233445566",
    "period_days": 7,
    "rate_limit_per_minute": 1000,
    "total_requests": 4213,
    "total_errors": 17,
    "daily": [
      { "day": "2025-09-15", "request_count": 642, "error_count": 3 },
      { "day": "2025-09-14", "request_count": 588, "error_count": 0 },
      { "day": "2025-09-13", "request_count": 601, "error_count": 5 }
    ]
  }
}

Handling 429 responses

When you hit the rate limit, the API returns a 429 status code with a Retry-After header indicating how many seconds to wait:

HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1726412400

{
  "success": false,
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded"
  }
}

Retry with exponential backoff

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 = parseInt(response.headers.get('Retry-After') || '1');
    const backoff = retryAfter * 1000 * Math.pow(2, attempt);

    console.log(`Rate limited. Retrying in ${backoff / 1000}s (attempt ${attempt + 1})`);
    await new Promise((resolve) => setTimeout(resolve, backoff));
  }

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

Best practices

  • Cache responses. If you are displaying form data on a dashboard, cache the API response for 30-60 seconds instead of fetching on every page load.
  • Use pagination wisely. Fetch the maximum per_page (100) to reduce the number of requests needed to retrieve all data.
  • Batch requests. Instead of making individual requests for each form, use the list endpoint with filters to get multiple resources in one call.
  • Use webhooks for real-time data. Instead of polling the API for new submissions, set up a webhook to receive push notifications. This eliminates unnecessary API calls entirely.
  • Monitor your usage. Check X-RateLimit-Remaining in your responses and slow down proactively when you are nearing the limit.
  • Contact us for higher limits. If your use case requires more than 1,000 requests per minute, reach out to discuss an Enterprise plan with custom limits.
$37 · paid once

Ready to Build Forms That Actually Convert?

Start free and keep the five forms for good, or pay once and unlock all of it — unlimited forms, ten team members, AI, CRM, white label and the API. No renewal, ever.

14-day money-backInstant accessNo subscription, ever
Rate Limits