Skip to main content

Overview

Dancity enforces rate limits to ensure platform stability and fair use across all API clients.

Limits

ScopeLimit
Global (per API key)120 requests / minute
VAS purchases (airtime, data, electricity, cable)30 requests / minute
OTP requests5 requests / 10 minutes
Bulk operations (bulk airtime, bulk data)10 requests / minute

Rate limit headers

Every response includes the following headers:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Handling 429 responses

When you exceed the limit, you receive:
{
  "statusCode": 429,
  "message": "Too Many Requests",
  "error": "Too Many Requests"
}
Implement exponential backoff:
async function fetchWithRetry(url, options, retries = 3) {
  for (let attempt = 0; attempt <= retries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) return response;

    if (attempt === retries) throw new Error("Rate limit exceeded after retries");

    // Exponential backoff: 1s, 2s, 4s
    const delay = Math.pow(2, attempt) * 1000;
    console.log(`Rate limited. Retrying in ${delay}ms...`);
    await new Promise((resolve) => setTimeout(resolve, delay));
  }
}

Best practices

For sending airtime or data to multiple recipients at once, use the bulk endpoints (POST /airtime/bulk, POST /buy-data/bulk). A single bulk request counts as one request against your rate limit.
Electricity meter and cable smartcard validation results can be cached client-side for a short period. There’s no need to re-validate on every page load.
Check X-RateLimit-Remaining before making bursts of requests. If it drops below 10, slow down or pause until X-RateLimit-Reset.