Error Handling

The Schedulala API uses conventional HTTP status codes and returns structured error responses to help you handle failures gracefully.

Error response format

All error responses share a consistent JSON structure. The success field is always false, and the error object contains a machine-readable code, a human-readable message, and optional details:

Error Response
{
"success": false,
"error": {
"code": "invalid_request",
"message": "The 'content' field is required",
"details": {
"field": "content",
"reason": "required"
}
}
}
FieldTypeDescription
successbooleanAlways false for errors
error.codestringMachine-readable error code (use this for programmatic handling)
error.messagestringHuman-readable description of the error
error.detailsobject | nullAdditional context (e.g., which field failed validation). Omitted when there is none.

Error codes

Use the error.code field to programmatically handle different error types:

CodeHTTP StatusDescription
invalid_request400Malformed request (missing fields, invalid JSON, etc.)
validation_error400Request validation failed (e.g., content too long for platform)
url_not_allowed400URL rejected (media-from-URL): must be a publicly reachable http(s) URL; private and internal addresses are blocked
sandbox_unsupported400Operation not available with test (sk_test_) keys; use a live key
unauthorized401Invalid or missing API key
forbidden403API key doesn't have permission for this operation
plan_limit_exceeded403Plan limit reached (upgrade to increase limits)
not_found404Resource not found
idempotency_conflict409Idempotency key reused with a different request body
media_too_large413Uploaded file exceeds the size limit
unsupported_media415Unsupported media type for the target platform
download_failed422Media could not be downloaded from the provided URL (media-from-URL)
rate_limit_exceeded429Too many requests — wait and retry with backoff
internal_error500Internal server error — retry with backoff
platform_error502Error from the social media platform — retry with backoff

Error handling examples

Always check the success field first, then handle specific error codes:

async function createPost(payload) {
const response = await fetch('https://schedulala.com/api/v1/posts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (!data.success) {
switch (data.error.code) {
case 'rate_limit_exceeded': {
// Wait until the rate limit window resets (ms timestamp)
const resetMs = response.headers.get('X-RateLimit-Reset');
const waitMs = resetMs
? Math.max(0, parseInt(resetMs, 10) - Date.now())
: 60000;
await sleep(waitMs);
return createPost(payload);
}
case 'platform_error':
// Social platform issue — retry with exponential backoff
console.error('Platform error:', data.error.message);
throw new RetryableError(data.error.message);
case 'validation_error':
// Fix the request — don't retry
console.error('Validation failed:', data.error.details);
throw new ValidationError(data.error.message, data.error.details);
case 'unauthorized':
// Check your API key
throw new AuthError('Invalid API key');
default:
throw new Error(data.error.message);
}
}
return data;
}

Best practices

Check the success field first

Every API response includes a success field. Check it before accessing data fields to avoid unexpected runtime errors in your application.

Handle specific error codes

Use error.code (not the HTTP status) for programmatic error handling. This gives you more granular control — for example, both forbidden and plan_limit_exceeded return HTTP 403, but require different handling.

Retry with exponential backoff

Implement retry logic with exponential backoff for these retryable errors:

Error CodeRetry?Strategy
rate_limit_exceededYesWait until the X-RateLimit-Reset timestamp (OAuth and device-flow 429s also send Retry-After)
platform_errorYesExponential backoff (1s, 2s, 4s, ...)
internal_errorYesExponential backoff (1s, 2s, 4s, ...)
All other 4xx errorsNoFix the request before retrying

Don't retry 4xx errors (except 429). Client errors like validation_error, unauthorized, and forbidden will return the same error every time. Fix the underlying issue before retrying.

Use idempotency keys for safe retries

When retrying POST requests, always include an Idempotency-Key header to prevent duplicate operations. See the Idempotency guide for details.

Tip: Log the full error response (including error.code, error.message, and error.details) in your application. This makes debugging much easier when issues arise.

Related