SalesLoft Rate Limits
Overview
SalesLoft uses cost-based rate limiting at 600 cost per minute. Each request costs 1 point by default, but deep pagination multiplies the cost. Rate limit state is returned in response headers.
Rate Limit Model
Cost per Request
| Page Range | Cost per Request | Example: 1000 records at 100/page | |------------|-----------------|-----------------------------------| | 1-100 | 1 point | Pages 1-10: 10 points | | 101-150 | 3 points | N/A for this example | | 151-250 | 8 points | N/A | | 251-500 | 10 points | N/A | | 501+ | 30 points | N/A |
Budget: 600 points/minute. A simple 10-page pagination costs 10 points. But paginating to page 500 costs 10 + 150 + 800 + 2500 = 3460 points (nearly 6 minutes of budget).
Response Headers
X-RateLimit-Limit-Per-Minute: 600
X-RateLimit-Remaining-Per-Minute: 487
Retry-After: 42 # Only present on 429 responses
X-Request-Id: abc-123 # For support tickets
Instructions
Step 1: Rate-Limit-Aware Client
import axios, { AxiosInstance } from 'axios';
class SalesloftRateLimiter {
private remaining = 600;
private resetAt = Date.now();
constructor(private client: AxiosInstance) {
client.interceptors.response.use(
(res) => {
this.remaining = parseInt(res.headers['x-ratelimit-remaining-per-minute'] || '600');
return res;
},
async (err) => {
if (err.response?.status === 429) {
const wait = parseInt(err.response.headers['retry-after'] || '60');
console.warn(`Rate limited. Waiting ${wait}s (X-Request-Id: ${err.response.headers['x-request-id']})`);
await this.sleep(wait * 1000);
return this.client.request(err.config);
}
throw err;
}
);
}
async throttledRequest<T>(fn: () => Promise<T>): Promise<T> {
if (this.remaining < 10) {
const waitMs = Math.max(0, this.resetAt - Date.now());
if (waitMs > 0) await this.sleep(waitMs);
}
return fn();
}
private sleep(ms: number) { return new Promise(r => setTimeout(r, ms)); }
}
Step 2: Pagination Cost Calculator
function paginationCost(totalRecords: number, perPage: number = 100): number {
const totalPages = Math.ceil(totalRecords / perPage);
let cost = 0;
for (let p = 1; p <= totalPages; p++) {
if (p <= 100) cost += 1;
else if (p <= 150) cost += 3;
else if (p <= 250) cost += 8;
else if (p <= 500) cost += 10;
else cost += 30;
}
return cost;
}
// Budget check before large exports
const totalPeople = 25000; // from metadata.paging.total_count
const cost = paginationCost(totalPeople);
const minutes = Math.ceil(cost / 600);
console.log(`Export will cost ${cost} points (~${minutes} minutes at rate limit)`);
Step 3: Queue-Based Throttling for Bulk Operations
import PQueue from 'p-queue';
// Max 5 concurrent, 10 per second (600/min = 10/sec)
const queue = new PQueue({ concurrency: 5, interval: 1000, intervalCap: 10 });
async function bulkCreatePeople(people: any[]) {
const results = await Promise.allSettled(
people.map(person =>
queue.add(() => api.post('/people.json', person))
)
);
const succeeded = results.filter(r => r.status === 'fulfilled').length;
console.log(`Created ${succeeded}/${people.length} people`);
}
Error Handling
| Scenario | Cost Impact | Strategy | |----------|-------------|----------| | Simple list (page 1-10) | 10 points | No throttle needed | | Full export (250 pages) | 910 points | ~2 min, add delays | | Bulk create (500 records) | 500 points | Queue with intervalCap | | Deep pagination (page 500) | 3460 points | Cache or use webhooks instead |
Resources
Next Steps
For security configuration, see salesloft-security-basics.