The Sprinklr API implements rate limiting to ensure fair usage and maintain optimal performance for all users. Understanding how rate limits work and how to work within them is essential for building reliable, production-ready integrations.
Rate limiting protects the API infrastructure and ensures that all customers get consistent, reliable performance. Without rate limits, a single integration making too many requests could degrade performance for everyone.
For your integration, rate limits mean:
- You need to design for efficiency from the start
- You should implement retry logic and backoff strategies
- You'll want to monitor your usage to avoid hitting limits
- You may need to cache data and batch operations strategically
The good news? With the right approach, you'll rarely hit rate limits, and when you do, your application will handle it gracefully and automatically recover.
Think of rate limiting like traffic lights on a busy highway. They prevent congestion and keep everything moving smoothly for everyone. Your job is to time your acceleration and plan your route efficiently.
The Sprinklr API uses a sliding window rate limit algorithm. This means your rate limit is calculated based on your requests over a rolling time period, not a fixed window that resets at specific times.
Example of sliding window:
If your limit is 60 requests per minute:
- At 10:00:00, you make 60 requests
- At 10:00:30, you can make more requests (oldest ones are now outside the 1-minute window)
- You don't have to wait until 10:01:00 to make more requests
Compare to fixed window:
- At 10:00:00, you make 60 requests
- You must wait until 10:01:00 before making any more requestsThis sliding window approach is more forgiving and allows for smoother request distribution.
Every API response includes three headers that tell you your current rate limit status:
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1709564820
Content-Type: application/json| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current time window | 1000 |
X-RateLimit-Remaining | Number of requests you can still make in this window | 847 |
X-RateLimit-Reset | Unix timestamp (seconds) when the limit fully resets | 1709564820 |
Node.js:
const response = await fetch('https://api-v3.sprinklr.com/api/v3/account', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Key': apiKey
}
});
const limit = response.headers.get('X-RateLimit-Limit');
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
console.log(`Rate limit: ${remaining}/${limit} requests remaining`);
console.log(`Resets at: ${new Date(reset * 1000).toISOString()}`);
// Check if you're getting close to the limit
if (remaining < limit * 0.1) { // Less than 10% remaining
console.warn('Approaching rate limit! Consider slowing down requests.');
}
const data = await response.json();Python:
import requests
from datetime import datetime
response = requests.get(
'https://api-v3.sprinklr.com/api/v3/account',
headers={
'Authorization': f'Bearer {access_token}',
'Key': api_key
}
)
limit = int(response.headers['X-RateLimit-Limit'])
remaining = int(response.headers['X-RateLimit-Remaining'])
reset = int(response.headers['X-RateLimit-Reset'])
print(f'Rate limit: {remaining}/{limit} requests remaining')
print(f'Resets at: {datetime.fromtimestamp(reset).isoformat()}')
# Check if approaching limit
if remaining < limit * 0.1:
print('WARNING: Approaching rate limit!')
data = response.json()PHP:
<?php
$ch = curl_init('https://api-v3.sprinklr.com/api/v3/account');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $accessToken,
'Key: ' . $apiKey
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
// Parse headers
preg_match('/X-RateLimit-Limit: (\d+)/', $headers, $limitMatch);
preg_match('/X-RateLimit-Remaining: (\d+)/', $headers, $remainingMatch);
preg_match('/X-RateLimit-Reset: (\d+)/', $headers, $resetMatch);
$limit = $limitMatch[1];
$remaining = $remainingMatch[1];
$reset = $resetMatch[1];
echo "Rate limit: {$remaining}/{$limit} requests remaining\n";
echo "Resets at: " . date('Y-m-d H:i:s', $reset) . "\n";
if ($remaining < $limit * 0.1) {
echo "WARNING: Approaching rate limit!\n";
}
$data = json_decode($body, true);
?>Java:
import java.net.http.*;
import java.time.Instant;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api-v3.sprinklr.com/api/v3/account"))
.header("Authorization", "Bearer " + accessToken)
.header("Key", apiKey)
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
int limit = Integer.parseInt(
response.headers().firstValue("X-RateLimit-Limit").orElse("0"));
int remaining = Integer.parseInt(
response.headers().firstValue("X-RateLimit-Remaining").orElse("0"));
long reset = Long.parseLong(
response.headers().firstValue("X-RateLimit-Reset").orElse("0"));
System.out.println("Rate limit: " + remaining + "/" + limit +
" requests remaining");
System.out.println("Resets at: " +
Instant.ofEpochSecond(reset).toString());
// Check if approaching limit
if (remaining < limit * 0.1) {
System.out.println("WARNING: Approaching rate limit!");
}
String data = response.body();Your rate limit depends on your Sprinklr account tier. Different tiers get different request allowances to match their usage needs.
| Tier | Requests per Minute | Requests per Hour | Daily Requests | Best For |
|---|---|---|---|---|
| Standard | 60 | 3,000 | 72,000 | Small teams, development/testing |
| Professional | 120 | 7,200 | 172,800 | Mid-size integrations, scheduled jobs |
| Enterprise | 300 | 18,000 | 432,000 | High-volume production systems |
| Custom | Custom | Custom | Custom | Contact your account manager |
Your tier is determined by your Sprinklr account settings. Check with your account administrator or contact your Sprinklr account manager to:
- Find out your current tier
- Understand what usage patterns fit your tier
- Upgrade your tier if you're consistently hitting limits
Note: Rate limits are applied per access token, not per account. If you have multiple integrations, each with its own token, they each get the full rate limit.
When you exceed your rate limit, you'll receive an HTTP 429 Too Many Requests response:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1709564880
Retry-After: 15
Content-Type: application/json{
"success": false,
"errors": [
{
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. You have made too many requests in the current time window.",
"details": {
"limit": 60,
"window": "1 minute",
"resetAt": "2024-03-04T16:48:00Z"
}
}
]
}What to do when you get a 429:
- Don't panic - This is a normal part of API usage
- Check the
Retry-Afterheader - Tells you how many seconds to wait - Wait the recommended time - Or use the
X-RateLimit-Resettimestamp - Retry the request - It should succeed after waiting
- Review your request patterns - Consider optimization strategies
The single most effective way to stay under rate limits is to use batch endpoints whenever possible.
❌ Don't make individual requests:
// 50 API calls, takes 50 of your rate limit
const accounts = [];
for (const accountId of accountIds) {
const response = await fetch(
`https://api-v3.sprinklr.com/api/v3/account?accountId=${accountId}`,
{ headers: { 'Authorization': `Bearer ${token}`, 'Key': key } }
);
const data = await response.json();
accounts.push(data.data);
}✅ Do use batch endpoints:
// 1 API call, takes 1 of your rate limit
const response = await fetch(
'https://api-v3.sprinklr.com/api/v3/account/batch',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Key': key,
'Content-Type': 'application/json'
},
body: JSON.stringify({
accountIds: accountIds // Up to 50 IDs
})
}
);
const data = await response.json();
const accounts = data.data;Impact: 50x reduction in API calls. If you're on the Standard tier (60 requests/minute), that's the difference between processing 60 accounts per minute vs 3,000 accounts per minute.
Cache responses for data that doesn't change frequently. Not everything needs to be fetched in real-time.
Node.js caching example:
class SprinklrCache {
constructor() {
this.cache = new Map();
this.ttls = new Map();
}
set(key, value, ttlSeconds = 300) { // Default 5 minutes
this.cache.set(key, value);
this.ttls.set(key, Date.now() + (ttlSeconds * 1000));
}
get(key) {
const ttl = this.ttls.get(key);
// Check if expired
if (!ttl || Date.now() > ttl) {
this.cache.delete(key);
this.ttls.delete(key);
return null;
}
return this.cache.get(key);
}
clear() {
this.cache.clear();
this.ttls.clear();
}
}
// Usage
const cache = new SprinklrCache();
async function getAccount(accountId) {
// Check cache first
const cacheKey = `account:${accountId}`;
const cached = cache.get(cacheKey);
if (cached) {
console.log('Cache hit!');
return cached;
}
// Fetch from API
console.log('Cache miss, fetching from API...');
const response = await fetch(
`https://api-v3.sprinklr.com/api/v3/account?accountId=${accountId}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Key': apiKey
}
}
);
const data = await response.json();
// Cache for 5 minutes
cache.set(cacheKey, data.data, 300);
return data.data;
}What to cache and for how long:
| Data Type | Recommended TTL | Rationale |
|---|---|---|
| Account metadata | 30-60 minutes | Changes infrequently |
| User profiles | 15-30 minutes | May change but not constantly |
| Messages/posts | 1-5 minutes | More dynamic content |
| Cases | 1-2 minutes | Changes as agents work on them |
| Configuration data | 1-24 hours | Rarely changes |
Queue your requests to ensure you never exceed your rate limit, even during traffic spikes.
Production-ready request queue:
class RateLimitedQueue {
constructor(requestsPerMinute = 60) {
this.requestsPerMinute = requestsPerMinute;
this.queue = [];
this.requestTimes = [];
this.processing = false;
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject });
this.process();
});
}
async process() {
// Prevent multiple process loops
if (this.processing) return;
this.processing = true;
while (this.queue.length > 0) {
// Clean up old request times (older than 1 minute)
const oneMinuteAgo = Date.now() - 60000;
this.requestTimes = this.requestTimes.filter(time => time > oneMinuteAgo);
// Check if we can make another request
if (this.requestTimes.length >= this.requestsPerMinute) {
// Calculate wait time until oldest request expires
const oldestRequest = this.requestTimes[0];
const waitTime = 60000 - (Date.now() - oldestRequest) + 100; // +100ms buffer
console.log(`Rate limit reached. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
// Process next request
const { requestFn, resolve, reject } = this.queue.shift();
this.requestTimes.push(Date.now());
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
}
// Small delay between requests to be gentle
await new Promise(resolve => setTimeout(resolve, 50));
}
this.processing = false;
}
getQueueSize() {
return this.queue.length;
}
getRecentRequestCount() {
const oneMinuteAgo = Date.now() - 60000;
return this.requestTimes.filter(time => time > oneMinuteAgo).length;
}
}
// Usage
const queue = new RateLimitedQueue(60); // Standard tier: 60 req/min
// All requests go through the queue
async function fetchAccount(accountId) {
return queue.add(async () => {
const response = await fetch(
`https://api-v3.sprinklr.com/api/v3/account?accountId=${accountId}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Key': apiKey
}
}
);
return response.json();
});
}
// Make 100 requests - they'll be automatically rate-limited
const promises = accountIds.slice(0, 100).map(id => fetchAccount(id));
const results = await Promise.all(promises);
console.log(`Processed ${results.length} accounts without hitting rate limit`);When you do hit a rate limit (or any temporary error), retry with exponential backoff.
Exponential backoff implementation:
async function withExponentialBackoff(fn, maxRetries = 5) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
// Check if it's a rate limit error
if (error.response?.status === 429) {
const resetHeader = error.response.headers.get('X-RateLimit-Reset');
const retryAfter = error.response.headers.get('Retry-After');
let waitTime;
if (retryAfter) {
// Use Retry-After header if provided
waitTime = parseInt(retryAfter) * 1000;
} else if (resetHeader) {
// Calculate from reset timestamp
waitTime = (parseInt(resetHeader) * 1000) - Date.now();
} else {
// Exponential backoff: 1s, 2s, 4s, 8s, 16s
waitTime = Math.min(Math.pow(2, attempt) * 1000, 30000);
}
console.log(`Rate limit hit. Waiting ${waitTime}ms before retry ${attempt + 1}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
// For other errors, use exponential backoff
if (attempt < maxRetries - 1) {
const waitTime = Math.pow(2, attempt) * 1000;
console.log(`Request failed. Waiting ${waitTime}ms before retry ${attempt + 1}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
}
throw lastError;
}
// Usage
const account = await withExponentialBackoff(async () => {
const response = await fetch(
`https://api-v3.sprinklr.com/api/v3/account?accountId=${accountId}`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Key': apiKey
}
}
);
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = response;
throw error;
}
return response.json();
});If you're polling for updates, consider these alternatives:
❌ Don't poll aggressively:
// Polls every 5 seconds - uses 720 requests/hour
setInterval(async () => {
const cases = await fetchNewCases();
processNewCases(cases);
}, 5000);✅ Do use webhooks (best option):
// Webhooks push updates to you - uses 0 API requests
app.post('/webhooks/sprinklr/case-created', (req, res) => {
const caseData = req.body;
processNewCase(caseData);
res.sendStatus(200);
});✅ Or increase polling interval:
// Polls every 60 seconds - uses 60 requests/hour (12x reduction)
setInterval(async () => {
const cases = await fetchNewCases();
processNewCases(cases);
}, 60000);✅ Or use smart polling with caching:
// Only poll if data might have changed
let lastModified = null;
setInterval(async () => {
const response = await fetch(
'https://api-v3.sprinklr.com/api/v3/cases/search',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Key': apiKey,
'If-Modified-Since': lastModified || ''
},
body: JSON.stringify({ status: 'OPEN' })
}
);
// 304 Not Modified - no new data, no processing needed
if (response.status === 304) {
console.log('No new cases');
return;
}
lastModified = response.headers.get('Last-Modified');
const cases = await response.json();
processNewCases(cases.data);
}, 30000);Instead of making all your requests at once, spread them out evenly.
Spread requests over time:
async function processInBatches(items, processFn, batchSize = 10, delayMs = 1000) {
const results = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
console.log(`Processing batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(items.length / batchSize)}`);
// Process batch in parallel
const batchResults = await Promise.all(
batch.map(item => processFn(item))
);
results.push(...batchResults);
// Wait before next batch (except for the last one)
if (i + batchSize < items.length) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
return results;
}
// Process 1000 accounts in batches of 10, with 1 second between batches
// Total time: ~100 seconds, stays well under rate limit
const accounts = await processInBatches(
accountIds,
id => fetchAccount(id),
10, // 10 at a time
1000 // 1 second between batches
);Here's a complete example that combines all these strategies:
class SprinklrAPIClient {
constructor(accessToken, apiKey, options = {}) {
this.accessToken = accessToken;
this.apiKey = apiKey;
this.baseUrl = 'https://api-v3.sprinklr.com';
// Configuration
this.requestsPerMinute = options.requestsPerMinute || 60;
this.cacheTTL = options.cacheTTL || 300000; // 5 minutes
this.maxRetries = options.maxRetries || 5;
// Components
this.cache = new Map();
this.queue = new RateLimitedQueue(this.requestsPerMinute);
this.metrics = {
totalRequests: 0,
cacheHits: 0,
cacheMisses: 0,
rateLimitHits: 0
};
}
async request(method, endpoint, options = {}) {
const { useCache = true, cacheTTL = this.cacheTTL, ...fetchOptions } = options;
const cacheKey = `${method}:${endpoint}:${JSON.stringify(fetchOptions.body || {})}`;
// Check cache for GET requests
if (method === 'GET' && useCache) {
const cached = this.getCached(cacheKey);
if (cached) {
this.metrics.cacheHits++;
console.log('Cache hit:', endpoint);
return cached;
}
this.metrics.cacheMisses++;
}
// Queue the request
const response = await this.queue.add(async () => {
return withExponentialBackoff(async () => {
this.metrics.totalRequests++;
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method,
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Key': this.apiKey,
'Content-Type': 'application/json',
...fetchOptions.headers
},
...fetchOptions
});
// Log rate limit status
const remaining = response.headers.get('X-RateLimit-Remaining');
const limit = response.headers.get('X-RateLimit-Limit');
console.log(`Rate limit: ${remaining}/${limit}`);
// Warning if approaching limit
if (remaining && limit && parseInt(remaining) < parseInt(limit) * 0.1) {
console.warn('WARNING: Less than 10% of rate limit remaining!');
}
if (response.status === 429) {
this.metrics.rateLimitHits++;
const error = new Error('Rate limit exceeded');
error.response = response;
throw error;
}
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = response;
throw error;
}
return response.json();
}, this.maxRetries);
});
// Cache successful GET responses
if (method === 'GET' && useCache && response.success) {
this.setCached(cacheKey, response, cacheTTL);
}
return response;
}
async get(endpoint, params = {}, options = {}) {
const queryString = new URLSearchParams(params).toString();
const url = queryString ? `${endpoint}?${queryString}` : endpoint;
return this.request('GET', url, options);
}
async post(endpoint, body, options = {}) {
return this.request('POST', endpoint, {
...options,
body: JSON.stringify(body)
});
}
getCached(key) {
const cached = this.cache.get(key);
if (!cached) return null;
if (Date.now() > cached.expiresAt) {
this.cache.delete(key);
return null;
}
return cached.data;
}
setCached(key, data, ttl) {
this.cache.set(key, {
data,
expiresAt: Date.now() + ttl
});
}
clearCache() {
this.cache.clear();
console.log('Cache cleared');
}
getMetrics() {
const cacheHitRate = this.metrics.totalRequests > 0
? (this.metrics.cacheHits / (this.metrics.cacheHits + this.metrics.cacheMisses) * 100).toFixed(2)
: 0;
return {
...this.metrics,
cacheHitRate: `${cacheHitRate}%`,
queueSize: this.queue.getQueueSize(),
recentRequests: this.queue.getRecentRequestCount()
};
}
}
// Usage
const client = new SprinklrAPIClient(accessToken, apiKey, {
requestsPerMinute: 60, // Standard tier
cacheTTL: 300000, // 5 minutes
maxRetries: 5
});
// Make requests - all the complexity is handled automatically
try {
// GET request with automatic caching
const account = await client.get('/api/v3/account', { accountId: '600057112' });
// POST request (not cached)
const messages = await client.post('/api/v3/message/search', {
platform: 'TWITTER',
limit: 50
});
// Check metrics
console.log('Client metrics:', client.getMetrics());
// Output: { totalRequests: 2, cacheHits: 0, cacheMisses: 1, rateLimitHits: 0,
// cacheHitRate: '0.00%', queueSize: 0, recentRequests: 2 }
} catch (error) {
console.error('API request failed:', error);
}Tracking your API usage helps you identify optimization opportunities before you hit limits.
Simple usage tracking:
class APIUsageTracker {
constructor() {
this.requests = [];
}
logRequest(endpoint, statusCode) {
this.requests.push({
endpoint,
statusCode,
timestamp: Date.now()
});
// Keep only last 24 hours
const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);
this.requests = this.requests.filter(r => r.timestamp > oneDayAgo);
}
getStats(timeWindowMinutes = 60) {
const cutoff = Date.now() - (timeWindowMinutes * 60 * 1000);
const recent = this.requests.filter(r => r.timestamp > cutoff);
const endpointCounts = {};
const statusCounts = {};
for (const request of recent) {
endpointCounts[request.endpoint] = (endpointCounts[request.endpoint] || 0) + 1;
statusCounts[request.statusCode] = (statusCounts[request.statusCode] || 0) + 1;
}
return {
totalRequests: recent.length,
timeWindow: `${timeWindowMinutes} minutes`,
requestsPerMinute: (recent.length / timeWindowMinutes).toFixed(2),
topEndpoints: Object.entries(endpointCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 5),
statusCodes: statusCounts,
rateLimitErrors: statusCounts[429] || 0
};
}
exportReport() {
const stats = this.getStats(60);
console.log('\n=== API Usage Report (Last Hour) ===');
console.log(`Total requests: ${stats.totalRequests}`);
console.log(`Requests per minute: ${stats.requestsPerMinute}`);
console.log(`Rate limit errors: ${stats.rateLimitErrors}`);
console.log('\nTop endpoints:');
stats.topEndpoints.forEach(([endpoint, count]) => {
console.log(` ${endpoint}: ${count} requests`);
});
console.log('\nStatus codes:');
Object.entries(stats.statusCodes).forEach(([code, count]) => {
console.log(` ${code}: ${count}`);
});
}
}
// Usage
const tracker = new APIUsageTracker();
// Log every API request
async function makeAPIRequest(endpoint) {
try {
const response = await fetch(`https://api-v3.sprinklr.com${endpoint}`, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Key': apiKey
}
});
tracker.logRequest(endpoint, response.status);
return response.json();
} catch (error) {
tracker.logRequest(endpoint, error.response?.status || 0);
throw error;
}
}
// Export report every hour
setInterval(() => {
tracker.exportReport();
}, 60 * 60 * 1000);Before deploying your integration to production, verify you've implemented these rate limit optimizations:
- Use batch endpoints wherever available (up to 50 resources per request)
- Implement exponential backoff for retry logic
- Monitor rate limit headers in all responses
- Handle 429 errors gracefully with automatic retry
- Log rate limit metrics to track usage patterns
- Implement request caching with appropriate TTLs
- Use a request queue to prevent bursts from hitting limits
- Replace polling with webhooks where possible
- Distribute requests evenly over time instead of bursting
- Set up alerting when approaching rate limits
- Implement circuit breakers to prevent cascading failures
- Use multiple access tokens if you need higher throughput
- Optimize cache invalidation strategy
- Monitor cache hit rates and adjust TTLs
- Load test your integration to verify it stays under limits
Symptoms:
- Frequent 429 errors
- Slow response times due to retries
- Requests taking much longer than expected
Solutions:
- Use batch operations - Are you making individual requests when you could batch?
- Implement caching - Are you requesting the same data repeatedly?
- Reduce polling frequency - Can you use webhooks or poll less often?
- Upgrade your tier - Contact your account manager if you've optimized but still need more capacity
Symptoms:
- Occasional 429 errors
- Happens during specific operations
- Works most of the time
Solutions:
- Implement request queuing - You're likely sending bursts of requests
- Add exponential backoff - Automatic retry will handle occasional limits
- Spread requests over time - Don't process large batches all at once
Symptoms:
- Getting rate limited sooner than tier indicates
- Limit headers show unexpected values
Solutions:
- Check your account tier - Verify with your Sprinklr administrator
- Check per-endpoint limits - Some endpoints may have stricter limits
- Verify you're not sharing tokens - Each token has its own limit counter
- Contact support - There may be custom limits on your account
Now that you understand rate limiting, explore these related topics:
- Error Handling - Handle rate limit errors and other API errors properly
- Best Practices - More optimization strategies for production systems
- Webhooks - Replace polling with real-time event notifications
- API Basics - Learn about batch operations and other core patterns
If you're consistently hitting rate limits even after optimization:
- Review your integration - Are you following all the strategies above?
- Contact your account manager - Discuss upgrading your tier
- Reach out to support - We can help identify optimization opportunities
Support resources:
- Technical support: support.sprinklr.com
- API documentation: This guide and related docs
- Account management: Contact your Sprinklr account manager