Rate Limits & Error Handling
The PostEverywhere API enforces rate limits to ensure fair usage and platform stability. Every response includes rate limit headers so you can build resilient integrations that handle errors gracefully.
Rate limit tiers
All API keys share the same rate limit tiers. Limits are enforced on a rolling window basis and apply independently per API key.
| Window | Limit | Applies to |
|---|---|---|
| Per minute | 60 requests | All endpoints |
| Per hour | 1,000 requests | All endpoints |
| Per day | 10,000 requests | All endpoints |
Burst protection
The per-minute limit prevents short bursts from overwhelming the API. Spread your requests evenly rather than sending them in rapid succession.
Posting rate limits
Posting rate limits protect your social accounts from platform-level bans. X/Twitter enforces a 50 posts/day limit; Instagram and LinkedIn have similar thresholds.
| Endpoint | Per minute | Per hour | Per day |
|---|---|---|---|
POST /posts | 20 requests | 100 requests | 500 requests |
AI rate limits
AI rate limits prevent cost abuse and ensure fair usage of generation resources.
| Endpoint | Per 5 minutes | Per hour |
|---|---|---|
POST /ai/generate-image | 50 requests | 200 requests |
Rate limit headers
Every API response includes these headers so you can track your usage in real time and avoid hitting limits.
| Header | Type | Description |
|---|---|---|
X-RateLimit-Limit | integer | Maximum number of requests allowed in the current window |
X-RateLimit-Remaining | integer | Number of requests remaining in the current window |
X-RateLimit-Reset | integer | Unix timestamp (seconds) when the current rate limit window resets |
Retry-After | integer | Seconds to wait before retrying (only present on 429 responses) |
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1740912060Handling 429 responses
When you exceed the rate limit, the API returns a 429 Too Many Requests status. Use the Retry-After header and implement exponential backoff for a robust integration.
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1740912072
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please wait before retrying.",
"details": "You have exceeded the 60 requests per minute limit."
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-03-02T10:30:00Z"
}
}Exponential backoff with retry
import time
import requests
BASE_URL = "https://app.posteverywhere.ai/api/v1"
API_KEY = "pe_live_your_key_here"
def api_request(method, path, **kwargs):
url = f"{BASE_URL}{path}"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
max_retries = 3
for attempt in range(max_retries):
response = requests.request(method, url, headers=headers, **kwargs)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
print(f"Rate limited. Retrying in {retry_after}s...")
time.sleep(retry_after)
continue
response.raise_for_status()
return response.json()
raise Exception("Max retries exceeded")
# Usage
posts = api_request("GET", "/posts?status=scheduled")const BASE_URL = "https://app.posteverywhere.ai/api/v1";
const API_KEY = "pe_live_your_key_here";
async function apiRequest(method, path, body) {
const maxRetries = 3;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(`${BASE_URL}${path}`, {
method,
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || String(2 ** attempt));
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise((r) => setTimeout(r, retryAfter * 1000));
continue;
}
if (!response.ok) {
const error = await response.json();
throw new Error(error.error?.message || `HTTP ${response.status}`);
}
return response.json();
}
throw new Error("Max retries exceeded");
}
// Usage
const posts = await apiRequest("GET", "/posts?status=scheduled");Error response format
All error responses follow the same envelope format. The error object always contains a code field (machine-readable), a message field (human-readable), and may include details for validation errors.
{
"error": {
"code": "invalid_request",
"message": "Validation failed",
"details": {
"content": "Content is required and must be a non-empty string.",
"account_ids": "At least one account ID is required."
}
},
"meta": {
"request_id": "req_xyz789",
"timestamp": "2026-03-02T10:30:00Z"
}
}{
"error": {
"code": "unauthorized",
"message": "Unauthorized. Invalid or expired API key."
},
"meta": {
"request_id": "req_err001",
"timestamp": "2026-03-02T10:31:00Z"
}
}Error codes
Use the code field to programmatically handle errors. The following codes are used across all endpoints.
| Code | Description |
|---|---|
rate_limit_exceeded | You have exceeded a rate limit. Check the Retry-After header. |
insufficient_credits | Not enough AI credits to complete the generation request. |
invalid_request | The request body is malformed or missing required fields. |
unauthorized | API key is missing, invalid, or has been revoked. |
forbidden | The API key does not have the required scope for this endpoint. |
not_found | The requested resource does not exist or belongs to a different organization. |
content_filtered | AI-generated content was blocked by safety filters. |
server_error | An unexpected server error occurred. Retry with exponential backoff. |
HTTP status codes
The API uses standard HTTP status codes. Success responses use 2xx codes, client errors use 4xx, and server errors use 5xx.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded. Response body contains the requested data. |
| 201 | Created | Resource was created successfully (e.g. new post, media upload initiated). |
| 400 | Bad Request | Request body is malformed or missing required fields. Check error.details for specifics. |
| 401 | Unauthorized | API key is missing, invalid, or expired. Check your key. |
| 402 | Payment Required | Insufficient AI credits for the requested generation. Upgrade your plan or purchase additional credits. |
| 404 | Not Found | The requested resource (post, account, media) does not exist or belongs to a different organization. |
| 429 | Too Many Requests | Rate limit exceeded. Check Retry-After header and wait before retrying. |
| 500 | Internal Server Error | Unexpected server error. Retry with backoff. If persistent, contact support. |
Best practices
Follow these patterns to build a reliable integration that stays well within rate limits and handles errors gracefully.
Batch where possible
When creating posts for multiple platforms, use a single POST /posts request with multiple account_ids instead of making separate calls. This reduces your request count significantly.
Cache account lists
Connected accounts rarely change. Cache GET /accounts responses for 5-15 minutes rather than fetching on every post creation. This eliminates unnecessary requests.
Poll efficiently
When checking post results, use reasonable polling intervals (every 10-30 seconds). Avoid tight loops. Consider webhook-style patterns by checking results in a scheduled job rather than in real time.
Implement exponential backoff
Always respect the Retry-After header on 429 responses. For 5xx errors, use exponential backoff starting at 1 second and doubling on each retry, up to a maximum of 3 attempts.
Monitor your usage
Log the X-RateLimit-Remaining header from responses. Set an alert when remaining requests drop below 10% of the limit to proactively throttle before hitting 429 errors.
Handle errors at every level
Check for network errors, HTTP status codes, and the error field in the response body. A 200 status with an error in the body still requires handling — for example, partial failures on multi-platform posts.
Frequently asked questions
What happens when I hit the rate limit?
Can I get higher rate limits?
Do rate limits apply per API key or per organization?
Related documentation
Build with confidence
Get your API key and start building a resilient social media integration today.