From salesloft-pack
Implements SalesLoft API rate limiting with backoff, budget tracking from headers, and pagination cost calculator. Handles 429 errors and optimizes throughput for deep pagination.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin salesloft-packThis skill is limited to using the following tools:
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.
Optimizes SalesLoft API rate limit costs via pagination avoidance, incremental sync, caching, and webhooks. For usage analysis and bulk operation planning.
Manages Salesforce API rate limits with jsforce quota checks, backoff retries for REQUEST_LIMIT_EXCEEDED, and throughput optimization. Use for error handling or limit monitoring.
Provides Salesbuildr API patterns: api-key header authentication, offset-based pagination (from/size), error handling, and rate limiting (500 req/10min). Use for CRM API integrations.
Share bugs, ideas, or general feedback.
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.
| 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).
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
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)); }
}
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)`);
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`);
}
| 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 |
For security configuration, see salesloft-security-basics.