Skip to main content

Rate Limits

The Neuroon API implements usage limits to ensure service stability.

Limits by plan

PlanSearches/monthProductsRequests/min
Trial1005010
Basic5,0001,00060
Growth25,00010,000120
Pro100,00050,000300
EnterpriseUnlimitedUnlimitedCustom

Response headers

Each response includes information about your limits:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640000000
HeaderDescription
X-RateLimit-LimitMaximum limit per window
X-RateLimit-RemainingRemaining requests
X-RateLimit-ResetUnix timestamp of reset

Error 429

When you exceed the limit:

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded the request limit",
"retryAfter": 30
}
}

Handling rate limits

async function searchWithRetry(query, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch('/api/search', {
method: 'POST',
body: JSON.stringify({ query }),
});

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 30;
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}

return response.json();
}
throw new Error('Rate limit exceeded after retries');
}

Best practices

Debounce searches

import { debounce } from 'lodash';

const search = debounce((query) => {
widget.search(query);
}, 300);

input.addEventListener('input', (e) => search(e.target.value));

Cache results

const cache = new Map();

async function searchWithCache(query) {
if (cache.has(query)) {
return cache.get(query);
}

const results = await api.search(query);
cache.set(query, results);

return results;
}

Batch synchronization

Instead of syncing products one by one:

// Bad: many requests
for (const product of products) {
await api.syncProduct(product);
}

// Good: one batch request
await api.syncProducts(products);

Increase limits

If you need more capacity:

  1. Upgrade your plan in the Dashboard
  2. Contact us for Enterprise plans
  3. Optimize your integration (cache, debounce, batch)