Hootsuite Rate Limits
Overview
Handle Hootsuite API rate limits. The API returns 429 Too Many Requests with Retry-After headers when limits are exceeded.
Rate Limits
| Endpoint | Limit | Window |
|---|---|---|
| General API | Varies by plan | Per minute |
| Message scheduling | ~100/hour | Per hour |
| Media upload | ~50/hour | Per hour |
| Token refresh | ~10/hour | Per hour |
Instructions
Step 1: Respect Retry-After Header
async function rateLimitedRequest(url: string, options: RequestInit = {}) {
const response = await fetch(url, {
...options,
headers: { 'Authorization': `Bearer ${process.env.HOOTSUITE_ACCESS_TOKEN}`, ...options.headers },
});
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
console.log(`Rate limited. Retrying in ${retryAfter}s`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
return rateLimitedRequest(url, options); // Retry
}
return response;
}
Step 2: Queue-Based Scheduling
import PQueue from 'p-queue';
const hootsuiteQueue = new PQueue({
concurrency: 1,
interval: 1000,
intervalCap: 2, // 2 requests per second
});
async function queuedSchedule(profileId: string, text: string, time: Date) {
return hootsuiteQueue.add(() =>
fetch('https://platform.hootsuite.com/v1/messages', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.HOOTSUITE_ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ text, socialProfileIds: [profileId], scheduledSendTime: time.toISOString() }),
})
);
}
Prerequisites
- An approved API budget, header baseline, draft-only sandbox profile, and bounded queue.
- Idempotency keys for mutations plus a reviewed recovery path for exhausted work.
Output
Return a rate-limit receipt with account scope, requested/limited/deferred counts, retry revision, idempotency state, queue health, draft/public assertion, and rollback reference. Exclude copy, media, handles, and credentials.
Error Handling
Stop for unknown profile, quota saturation, an attempt to replay a public mutation, or a public-post path during recovery. Defer or cancel work rather than bypassing approval or account scope.
Examples
scope=sandbox-brand; requested=100; limited=3; deferred=3; retry=v2; idempotent=pass; public_posts=0; rollback=limits-r7 proves bounded handling.
Resources
Next Steps
For security, see hootsuite-security-basics.