| 400 | invalid_parameter | A query or body parameter is missing, malformed, or out of range (including timestamps without an explicit Z or offset) |
| 400 | invalid_request | The scheduling service rejected the post payload |
| 400 | invalid_media | An object_key that is unknown or not yours; upload first via POST /v1/media |
| 400 | media_not_uploaded | The upload was presigned but the bytes were never PUT (or the file is empty) |
| 400 | unsupported_media_type | Not a supported image (JPG, PNG, WEBP, or GIF); videos land here too |
| 400 | media_too_large | Over the size cap: 5MB for images, 15MB for GIFs |
| 400 | fetch_failed | The MCP upload_media_from_url download failed, timed out, or followed too many redirects |
| 400 | url_not_allowed | The MCP upload_media_from_url URL is not plain public https (private or reserved addresses, embedded credentials, and non-https schemes are rejected) |
| 400 | invalid_source | POST /v1/datasets was sent a source it does not accept. The list is in the endpoint reference, and it includes research |
| 400 | system_list_not_supported | A system people-list (Followers, Following, Repliers, Reposters) was used where only a list you created works: reading its members, or pointing POST /v1/datasets with source: "research" at it |
| 400 | range_too_large | Analytics range beyond the 366-day maximum |
| 400 | mirror_rejected | The mirror post on POST /v1/posts/draft cannot be used as a shape (too thin, carries a link, or is engagement bait); the message names the reason |
| 400 | invalid_collection | Unknown or unusable collection id on POST /v1/posts/draft; the message lists the ids that work |
| 400 | unknown_creator | SuperX has no posts for that creator handle, so it cannot learn the style |
| 400 | creator_style_unavailable | A style guide for that creator could not be built (not enough public posts). Terminal: retrying will not help |
| 400 | dataset_has_no_people | The dataset holds no people to add to a contact list: own-content datasets (has_people: false) hold posts, and rows without an X account id are skipped |
| 400 | not_enough_posts | POST /v1/context/style-guide/regenerate needs at least 5 recent posts on the account to read a style from. Terminal until the account posts more |
| 400 | account_not_linked | POST /v1/dm/campaigns needs a connected X account on the sending account; connect it in the SuperX app |
| 401 | unauthorized | Missing or malformed Authorization header |
| 401 | invalid_api_key | Unknown or revoked key |
| 403 | insufficient_scope | Read-only key used on a non-GET endpoint |
| 403 | writes_main_account_only | Write attempted for an account shared with you (shared accounts are read-only through the API), or a /v1/tags write for an account other than your main account. Your own linked accounts accept writes |
| 403 | editor_restricted | Context write on an account shared with you with editor permission; only the owner can change those settings (queue settings stay editable) |
| 403 | onboarding_required | Finish onboarding in the SuperX app before scheduling posts |
| 403 | post_quota_exceeded | Post quota for the billing period is used up |
| 403 | reauth_required | The connected X account must be re-authorized in the SuperX app before it can publish. Returned by scheduled_for: "now" and article publishing |
| 403 | dm_not_in_plan | The account’s plan carries no DM allowance, so POST /v1/dm/campaigns cannot queue anything. Check GET /v1/dm/limits |
| 403 | cap_reached | A plan limit on signal agents, or on the signals one agent may hold, is reached. Pause or delete one, or upgrade |
| 403 | (legacy string) | Subscription lapsed; see above |
| 404 | account_not_found | account_id is not one of your accounts |
| 404 | not_found | No such resource for this account (for example a scheduled post id) |
| 404 | contact_not_found | The id is not one of the account’s contacts. Returned by GET /v1/contacts/{id} and POST /v1/contacts/{id}/notes; contacts are your engagers, contact-list members and signal leads |
| 404 | note_not_found | No note with that id belongs to the contact in the path |
| 404 | list_not_found | The contact list id is not one of your lists. Also returned when a signal agent’s destination_list_id is not usable |
| 404 | feed_not_found | No Engage feed with that id belongs to this account |
| 404 | x_list_not_found | The X list is private, deleted, or never existed. Only public X lists can be used as an Engage feed source or a list_watch signal |
| 404 | user_not_found | No X account matches that handle (contact-list adds, profile_watch / follower_watch signals, GET /v1/x/users/{handle} and its /posts) |
| 404 | post_not_found | No public post with that id on the live lookups (GET /v1/x/posts/{id} and its /replies, and POST /v1/engage/reply-draft with a post_id): deleted, protected, or the wrong id. The upstream read reports a missing post and a failed read identically, so a transient failure can surface here too; retry once before concluding the post is gone |
| 404 | agent_not_found | The agent id is not one of your signal agents |
| 404 | signal_not_found | The signal id does not belong to the agent in the path |
| 404 | lead_not_found | No lead with that id belongs to this account. Lead ids come from GET /v1/signals/leads and are not X user ids |
| 404 | cover_style_not_found | The style_id is not one of your saved cover styles; list them at GET /v1/cover-styles |
| 404 | product_not_found | No product with that id belongs to this account. Product ids come from GET /v1/context; returned by POST /v1/context/products/{id}/scrape |
| 404 | campaign_not_found | No DM campaign with that id belongs to this account, or it queued nothing in the first place (every recipient was skipped, so data.id came back null), or every message it queued has been sent or cancelled. Campaign ids come from POST /v1/dm/campaigns |
| 404 | dataset_not_found | No dataset with that id belongs to this key, or it expired (datasets are kept for 30 days). List them at GET /v1/datasets |
| 409 | idempotency_key_reuse | Same Idempotency-Key with a different request body |
| 409 | idempotency_in_flight | An earlier request with this Idempotency-Key is still publishing. Wait for the Retry-After delay and retry the SAME key; it will never publish twice |
| 409 | post_already_published | The post has already gone out on X, so it cannot be published again |
| 409 | creator_style_pending | The creator’s style guide is being prepared; retry the same request in about a minute |
| 409 | duplicate_signal | The agent already watches that target. An agent may hold each target once |
| 409 | feed_limit_reached | The account already holds the maximum number of saved Engage feeds (8). Delete one first |
| 409 | profile_not_synced | The account’s X profile has not synced into SuperX yet, so GET /v1/engage/mentions has no handle to search for. Open the account in the SuperX app once, then retry |
| 409 | collection_in_progress | Another background audience collection, research run or refinement is still running for this account. Poll it with GET /v1/datasets/{id} and start the next one when it finishes |
| 409 | dataset_not_ready | The dataset id is valid but the dataset is not ready. The error carries the current dataset_status: collecting finishes on its own (poll GET /v1/datasets/{id}), failed has to be rebuilt in the SuperX app |
| 422 | post_has_no_text | POST /v1/engage/reply-draft read the post you named but it carries no text to reply to (an image or video with no caption). Supply the wording yourself in post instead. The credits are refunded |
| 422 | scrape_failed | A page could not be read (POST /v1/context/products/{id}/scrape, POST /v1/signals/icp/expand-from-url): it blocked the read, moved, or carries no usable text. The message says what happened. A transient failure answers 502 upstream_error instead, so a scrape_failed is worth fixing rather than retrying |
| 429 | rate_limited | Rate limit exceeded; honor Retry-After. Also returned by POST /v1/signals/icp/expand-from-url when more than 10 website prefills are run in 10 minutes, a short-term limit separate from the daily page-read budget |
| 429 | media_quota_exceeded | Daily media upload limit (100 per key) reached; honor Retry-After |
| 429 | ai_credits_exhausted | The account’s AI credit pool is used up (AI cover generation, post drafting, reply drafts, remix and the /v1/tools/* helpers). Carries credits_required, credits_remaining and reset_at, plus a Retry-After header. See Credits |
| 429 | ai_action_limited | A count limit for this AI action is used up. Carries scope, retry_after, reset_at and a Retry-After header; the daily counters reset at midnight UTC. scope: "account" is your own ceiling: your plan’s daily cap for the action, the once-an-hour limit on POST /v1/context/style-guide/regenerate (here reset_at is an hour after the last SUCCESSFUL run, not midnight), the 3 live style-guide attempts a day that same endpoint allows an account with fewer than 5 stored posts, or the 20 page reads a day shared with the SuperX app that POST /v1/context/products/{id}/scrape and POST /v1/signals/icp/expand-from-url draw on. scope: "platform" is the platform-wide fair-use ceiling on live-data actions, shared with every SuperX account, so your own allowance is untouched and the fix is to wait and retry |
| 429 | dm_limit_reached | The account’s DM allowance is used up. Carries scope (month or day) and a Retry-After header; the monthly refusal also carries reset_at. These are PLAN limits, not AI credits, so GET /v1/dm/limits is where the numbers live. On scope: "day", spread: true places the campaign over the coming days instead |
| 429 | collection_quota_exceeded | Today’s dataset collections are used up (10 per account per day, shared with the collections Ask SuperX runs in the app; a refinement counts as one). Carries retry_after, limit and reset_at, plus a Retry-After header; the counter resets at midnight UTC |
| 429 | lookup_quota_exceeded | The daily live X lookup allowance (300 per account, shared with Ask SuperX in the app) is used up, or it could not be verified. Carries retry_after, limit and reset_at, plus a Retry-After header; the counter resets at midnight UTC. See Rate limits |
| 500 | internal_error | Unexpected server error |
| 502 | upstream_error | A dependent SuperX service returned an unexpected response |
| 502 | generation_failed | Every draft in a POST /v1/posts/draft call failed to generate; all credits for the call were refunded |
| 503 | media_not_configured | Media storage is not configured on this server; try again later |
| 503 | accounts_unavailable | Linked and shared account verification temporarily unavailable (main account still works) |
| 503 | upstream_unavailable | The scheduling service is temporarily unreachable; safe to retry (reuse your Idempotency-Key on POST) |