Every error the Reelspan API returns: the error body, HTTP statuses, request error codes and per-network result codes for TikTok, YouTube, Instagram and more.
There are two kinds of error, and a client should handle both:
- The request is refused. You get an HTTP error status and an error body. Nothing was posted.
- The request is accepted, but a network fails. The request succeeds, and that network's entry in
results has success: false with an error_code. The other networks are not affected.
A refused request answers with this JSON:
{
"success": false,
"message": "This API key does not have the \"publish\" scope",
"error_code": "INSUFFICIENT_SCOPE"
}
- Branch on
error_code. The message is written for people and can change.
- Request error codes are UPPER_CASE; network result codes are lower_case.
- Some errors add fields:
usage on a monthly limit, platform when one network's rule refused the request, invalid_platforms when no requested network can be used, api_url on a 421.
- A few errors have no
error_code, only message (for example an unknown route, an invalid timezone or a key that is wrong). Fall back on the HTTP status.
- Server errors use
error instead of message: { "success": false, "error": "Internal server error" }.
| Status |
Meaning |
What to do |
| 200 |
Done, or moved to the background (see Async posts). Check each network's success. |
|
| 201 |
Created (approval links). |
|
| 202 |
Scheduled or queued; the body has a job_id. |
|
| 400 |
The request is invalid: a missing or wrong field, an unknown network, an unsupported file. |
Fix the request; retrying won't help. |
| 401 |
No key, a wrong key, a revoked or expired one. |
Check the Authorization: Bearer header. |
| 403 |
The key can't do this: a missing scope, a profile it isn't allowed, a plan limit, or a suspended workspace. |
Use another key or plan. |
| 404 |
No such profile, post, job or media, or the key can't see it. |
|
| 409 |
A conflict: the request is still running, the id is taken, or a scheduled post is already publishing. |
See the code. |
| 413 |
A file is larger than your plan or the library allows. |
Send a smaller file or upgrade. |
| 421 |
An API key was sent to the dashboard's address instead of the API. |
Use https://api.reelspan.com/v1. |
| 429 |
Too many requests, too many failed keys, or a monthly limit reached. |
Wait for Retry-After when present. |
| 500 |
Something broke on Reelspan's side. |
Retry with the same Idempotency-Key. |
| 502 |
A network didn't answer a lookup Reelspan made for you (for example TikTok creator info), or the AI provider failed. |
Retry later. |
| 503 |
Reelspan is briefly in maintenance, or a feature isn't set up on this server. |
Wait for Retry-After. |
| Code |
Status |
Meaning |
INSUFFICIENT_SCOPE |
403 |
The key lacks the scope this call needs (publish, read, profiles, analytics or webhooks). |
PROFILE_FORBIDDEN |
403 |
The key is limited to other profiles, or an account-wide webhook was set with a profile-limited key. |
RATE_LIMITED |
429 |
Too many requests in the current window; see Rate limits. Also too many credential connection attempts or manual webhook sends. |
AUTH_RATE_LIMITED |
429 |
Too many failed keys from your IP address (10 in 5 minutes). Retry-After: 300. |
USE_API_HOST |
421 |
An API key was sent to app.reelspan.com. The body's api_url is where it belongs. |
WORKSPACE_SUSPENDED |
403 |
The workspace is suspended. Contact support. |
USER_SUSPENDED |
403 |
The signed-in user (MCP with OAuth) is suspended. |
TWO_FACTOR_REQUIRED |
401 |
Dashboard sessions only: enter the authenticator code first. |
MAINTENANCE |
503 |
Reelspan is under maintenance. Retry after Retry-After seconds. |
| Code |
Status |
Meaning |
INVALID_REQUEST |
400 |
A field is missing or malformed, or a network's own rule failed before posting (YouTube needs a title, Pinterest a pinterest_board_id, Reddit a reddit_subreddit; the body names the platform). |
INVALID_PLATFORM |
400 |
A name in platform[] isn't a network Reelspan posts to. |
UNSUPPORTED_POST_TYPE |
400 |
A network doesn't take this kind of post (for example text to Instagram, or a document anywhere but LinkedIn). |
TITLE_REQUIRED |
400 |
Text and document posts need title. |
MEDIA_REQUIRED |
400 |
The post needs a video, photos or a PDF (file, URL or media id). |
INVALID_MULTIPART |
400 |
The body isn't valid multipart/form-data, or has too many fields or files, or a field that is too long. |
TOO_MANY_MEDIA_URLS |
400 |
More than 100 media URLs in one request. |
QUEUE_FULL |
400 |
add_to_queue: the profile's queue has no free slot in the next 30 days. |
USAGE_LIMIT |
429 |
A repeating series would go over your monthly uploads. |
TEST_LIMIT |
429 |
A test key workspace sent 500 test posts today. |
REQUEST_ID_IN_USE |
409 |
Your request_id has been used before. |
IDEMPOTENCY_KEY_IN_USE |
409 |
The first request with this Idempotency-Key is still running. Retry in a few seconds. See Retrying safely. |
A request that would go over the monthly upload limit is refused with 429 and the current usage (count, limit, last_reset) in the body. When none of the requested networks can be used (none connected, all needing reconnection), the request is refused with 400 and invalid_platforms, giving the reason for each.
| Code |
Status |
Meaning |
FILE_TOO_LARGE |
413 |
Over your plan's video size, 20 MB for a photo or 100 MB for a PDF. See Large files. |
UNSUPPORTED_MEDIA |
400 |
Not a file type Reelspan takes (SVG, BMP and TIFF, for example). |
WRONG_MEDIA_KIND |
400 |
A photo where a video was expected, or the other way round. |
EMPTY_FILE |
400 |
The file is empty. |
URL_FETCH_FAILED |
400 |
Reelspan couldn't download the media URL (not https, not public, a private address, an error or too many redirects). |
MEDIA_NOT_FOUND |
400 / 404 |
A media_id doesn't exist, belongs to another workspace, is the wrong kind, or was deleted. |
UPLOAD_NOT_FOUND |
404 |
A direct upload's id is unknown or expired. |
PARTS_REQUIRED |
400 |
Completing a direct upload without its parts. |
LIBRARY_FULL |
413 |
The media library has no room left on your plan. |
| Code |
Status |
Meaning |
scheduled_post_in_progress |
409 |
The scheduled post is publishing or due within a minute; it can't be edited or cancelled. |
NOTHING_TO_RETRY |
409 |
No network of this post failed (or the ones you named didn't). |
retry_media_expired |
404 |
The post's media has been deleted; post it again with the file. |
NOT_FOUND |
404 |
No such request, job or posts, or the key can't see them. |
NOT_SCHEDULED |
400 / 409 |
Only scheduled posts can go in an approval link; or the post was already published or cancelled. |
COMMENT_REQUIRED |
400 |
Asking for changes on an approval link needs a note. |
| Code |
Status |
Meaning |
PROFILE_NOT_FOUND |
404 |
No profile with this username in your workspace. |
PROFILE_LIMIT_REACHED |
403 |
Your plan's profile count is used up. See Plans and limits. |
PROFILE_EXISTS |
409 |
A profile with this username already exists. |
INVALID_USERNAME / INVALID_DISPLAY_NAME |
400 |
The profile's username or display name isn't allowed. |
profile_platform_mapping_invalid |
404 |
The profile has no account on this network (Pinterest boards, TikTok creator info). |
reauth_required |
409 |
The account must be reconnected (TikTok creator info). |
tiktok_unavailable |
502 |
TikTok didn't answer the creator info lookup. |
NOT_OAUTH |
400 |
The network connects with credentials, not OAuth: use the hosted connect page. |
UNSUPPORTED_PLATFORM |
400 |
The network can't be connected through OAuth. |
PROVIDER_NOT_CONFIGURED |
400 |
The network's OAuth app isn't set up on this server. |
ACCESS_DENIED |
403 |
The white-label connect link is read-only or doesn't offer this network. |
INVALID_WEBHOOK |
400 |
The webhook URL isn't allowed (not https, or a private address) or an event name is unknown. |
When connecting with credentials (POST /v1/accounts/{platform}), a refusal from the network comes back as 400 with the network's code in upper case, such as INVALID_TOKEN, INVALID_CREDENTIALS, INVALID_WEBHOOK or INVALID_SERVER, or 403 PLATFORM_DISABLED.
A browser connect flow (OAuth or the hosted connect page) can't answer with JSON, so it sends the person back to your redirect with connect_status=error, an error_code (INVALID_STATE for an expired link, ACCESS_DENIED, CONNECTION_FAILED, NOT_SUPPORTED, RATE_LIMITED, WORKSPACE_SUSPENDED or PROFILE_NOT_FOUND) and usually an error_description. A person who cancels comes back with connect_status=cancelled.
| Code |
Status |
Meaning |
AI_CREDITS_EXHAUSTED |
429 |
No AI caption credits left this month. |
NOTHING_TO_ADAPT |
400 |
Nothing to write captions from: add a video, photos or a caption. |
VIDEO_TOO_LONG |
400 |
Videos up to 5 minutes can be analysed. |
AI_PROVIDER_ERROR / AI_BAD_OUTPUT |
502 |
The AI provider failed or answered with something unusable. Retry; no credit is charged. |
AI_NOT_CONFIGURED |
503 |
AI captions aren't set up on this server. |
Each network in results (and in Post status and upload_completed webhooks) has its own outcome:
{
"tiktok": { "success": true, "url": "https://www.tiktok.com/@mybrand/video/7441…", "post_id": "7441…" },
"instagram": { "success": false, "error": "Instagram could not process the video: ERROR", "error_code": "instagram_processing_failed" },
"x": { "success": false, "skipped": true, "skip_reason": "profile_platform_not_configured", "error": "Profile my-brand has no X account configured", "error_code": "profile_platform_mapping_invalid" }
}
A failed network has error (for people) and error_code (for code). A network that was never tried also has skipped: true and a skip_reason. Failures that were temporary on the network's side (its 5xx answers, its rate limits, timeouts) are retried automatically, up to four attempts in all, before the result is final.
Many codes are built from what the network said: tiktok_<TikTok's code>, youtube_<YouTube's reason>. Treat any code you don't know by its prefix and the error text.
| Code |
Meaning |
Fix |
reauth_required |
The network refused the account's access (revoked, expired or missing a permission). The account is marked for reconnection and a social_account_reauth_required webhook is sent. |
Reconnect the account, then Retry. |
profile_platform_mapping_invalid |
Skipped: the profile has no active account on this network (skip_reason: profile_platform_not_configured). |
Connect one. |
token_error |
The network refused to refresh the account's token. |
Reconnect. |
media_required |
The network needs media this post doesn't have, such as a carousel of videos to a network that takes only photos. |
|
file_too_large |
Over this network's own file limit (Telegram 50 MB, Discord 10 MB, Mastodon 99 MB…). See Video requirements. |
|
processing_timeout |
The server (Mastodon, Lemmy) was still processing the media when Reelspan stopped waiting. |
Check the post; retry. |
platform_disabled |
Posting to this network is switched off for now. |
Try later. |
workspace_suspended |
The workspace was suspended before the post ran. |
Contact support. |
cancelled |
A scheduled post was cancelled. |
|
internal_error |
Something broke on Reelspan's side; it was retried first. |
Retry. |
| Code |
Meaning |
tiktok_privacy_unavailable |
The privacy_level isn't one this account may use. The message lists the allowed ones. |
tiktok_duration_too_long |
Longer than this account may post. |
tiktok_processing_timeout |
TikTok was still processing when Reelspan stopped waiting. |
tiktok_spam_risk_too_many_posts |
TikTok's daily post limit for this account was reached. |
tiktok_spam_risk_user_banned_from_posting |
TikTok has blocked this account from posting. |
tiktok_reached_active_user_cap |
TikTok's daily limit of posting users for Reelspan's app was reached. |
tiktok_unaudited_client_can_only_post_to_private_accounts |
TikTok accepts posts only to private accounts from this app for now. |
tiktok_url_ownership_unverified |
TikTok hasn't verified the domain photos are served from. |
tiktok_rate_limit_exceeded |
TikTok's rate limit; retried automatically. |
tiktok_<reason> |
Any other refusal or failure, with TikTok's own reason. |
| Code |
Meaning |
youtube_quotaExceeded, youtube_uploadLimitExceeded |
YouTube's daily limit was reached. Try again tomorrow. |
youtube_youtubeSignupRequired |
The Google account has no YouTube channel. Create one and reconnect. |
youtube_forbidden |
YouTube refused the request for this account. |
youtube_rejected |
YouTube rejected the upload. |
youtube_<reason> / youtube_error |
Any other YouTube error, with its reason. |
| Code |
Meaning |
instagram_processing_failed, facebook_processing_failed |
The network couldn't process the media. |
instagram_processing_timeout |
Instagram was still processing when Reelspan stopped waiting. |
facebook_page_required, facebook_page_not_connected |
No Facebook Page is chosen for the profile, or the Page isn't connected. |
meta_permission_denied |
A permission was removed; the account is marked for reconnection. |
meta_rate_limited |
Meta's rate limit; retried automatically. |
unsupported_media_type, not_found, meta_error |
Other Graph API refusals. |
| Code |
Meaning |
x_payment_required |
X wants payment for the call. |
x_media_failed, x_processing_timeout |
X couldn't process the media, or was still processing. |
x_rate_limited, x_error |
X's rate limit (retried), or another X error. |
threads_processing_failed, threads_processing_timeout, threads_error |
Threads couldn't process the media, was too slow, or refused. |
linkedin_processing_failed, linkedin_processing_timeout, linkedin_upload_failed, linkedin_error |
LinkedIn media or post errors. |
linkedin_version_sunset |
LinkedIn retired the API version in use; Reelspan has to update. Contact support. |
pinterest_blocked_content |
Pinterest blocked the content or link. |
pinterest_processing_failed, pinterest_processing_timeout, pinterest_upload_failed, pinterest_error |
Pinterest media or Pin errors. |
bluesky_video_too_large |
Over Bluesky's 100 MB. Send bluesky_compress=true to compress it. |
bluesky_video_limit |
Bluesky's daily video limit for the account is used up. |
bluesky_email_unconfirmed |
Bluesky needs the account's email confirmed before it takes video. |
bluesky_processing_failed, bluesky_processing_timeout, bluesky_upload_failed, bluesky_error |
Bluesky video or post errors. |
invalid_app_password |
The Bluesky app password no longer works. Reconnect. |
| Code |
Meaning |
subreddit_not_found, reddit_error |
The subreddit doesn't exist, or Reddit refused. |
location_required, google_business_error |
Choose a Business Profile location, or Google refused. |
invalid_chat, bot_not_admin, telegram_error |
Telegram: the chat is wrong, or the bot isn't an admin there. |
invalid_webhook, discord_error |
Discord: the webhook URL is wrong or was deleted. |
channel_not_found, not_in_channel, invalid_webhook, slack_error |
Slack: the channel is wrong, or the bot isn't in it. |
invalid_server, invalid_token, mastodon_error |
Mastodon. |
invalid_key, invalid_relay, invalid_media_server, nostr_media_error, nostr_relays_failed |
Nostr. |
community_not_found, lemmy_error |
Lemmy. |
invalid_site, invalid_credentials, insufficient_role, wordpress_error |
WordPress. |
title_required, publication_required, devto_error, hashnode_error |
Dev.to and Hashnode. |
invalid_company, invalid_forum, whop_error |
Whop. |
list_not_found, listmonk_error |
Listmonk. |
sandbox_rejected, sandbox_unavailable |
The sandbox network, on request. |
For symptoms and fixes, see Troubleshooting.
A network can succeed and still carry warnings: text cut to fit, links removed from an X post, a long post turned into a thread, extra photos left out, or a first comment the network refused. The post is live; the warning says what changed.