Rate Limiting
The Cashfin Business API implements rate limiting to ensure fair usage and protect the platform from abuse.
Rate Limits
| Plan | Requests per Second | Requests per Minute | Requests per Day |
|---|---|---|---|
| Free | 5 | 60 | 1,000 |
| Starter | 10 | 300 | 10,000 |
| Professional | 25 | 1,000 | 100,000 |
| Enterprise | Custom | Custom | Custom |
TIP
Need higher limits? Contact us to discuss enterprise options.
Rate Limit Headers
Every API response includes headers to help you track your usage:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640995200| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Unix timestamp when the rate limit resets |
Rate Limit Exceeded Response
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"success": false,
"error": "Rate limit exceeded. Please try again later.",
"retry_after": 30
}The response includes a Retry-After header indicating seconds until you can retry.
Best Practices
1. Implement Exponential Backoff
When you receive a 429 response, wait before retrying:
async function apiRequestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get("Retry-After") || 30;
await new Promise((resolve) =>
setTimeout(resolve, retryAfter * 1000 * Math.pow(2, attempt))
);
continue;
}
return response;
}
throw new Error("Max retries exceeded");
}2. Cache Responses
Cache frequently accessed data like product lists to reduce API calls:
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
async function getProducts() {
const cacheKey = "products";
const cached = cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const response = await fetch(
"https://api.cashfin.africa/business/product/list",
{
headers: { Authorization: API_KEY },
}
);
const data = await response.json();
cache.set(cacheKey, { data, timestamp: Date.now() });
return data;
}3. Use Batch Operations
When available, use batch endpoints instead of multiple individual requests:
// ❌ Avoid: Multiple individual requests
for (const product of products) {
await updateProduct(product.id, product);
}
// ✅ Better: Single batch request (when available)
await updateProducts(products);4. Monitor Your Usage
Track your rate limit consumption in your application:
function handleRateLimitHeaders(response) {
const remaining = response.headers.get("X-RateLimit-Remaining");
const limit = response.headers.get("X-RateLimit-Limit");
if (remaining < limit * 0.1) {
console.warn(`Rate limit warning: ${remaining}/${limit} remaining`);
}
}Idempotency
For write operations (POST, PATCH), use the Idempotency-Key header to prevent duplicate requests:
curl -X POST "https://api.cashfin.africa/business/product/create" \
-H "Authorization: cs_your_client_secret" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-request-id-12345" \
-d '{"title": "Widget", "price": 99.99}'Idempotency keys:
- Must be unique per request
- Are valid for 24 hours
- Ensure the same request isn't processed twice
Rate Limit Exceptions
The following endpoints have separate, more generous limits:
| Endpoint | Special Limit |
|---|---|
GET /business/product/list | 100 req/min |
GET /business/product/details/:id | 200 req/min |
| Webhook endpoints | No limit |
INFO
Rate limits are applied per API key, not per IP address. Using multiple keys from the same account doesn't bypass limits.