Skip to main content
Use each error code to choose recovery.

Getting 400?

Fix your request body. See validation errors.

Getting 401 or 402?

Read the challenge and payment options. Never start checkout automatically. See common errors.

Getting 429?

Implement backoff. See retry strategy or rate limits.

Quick reference

Start with HTTP status. Retry only when stated.

400 request validation

Retry: no. Fix the body, query, or path. Covers invalid_input, invalid_json, invalid_id, invalid_tweet_url, invalid_tweet_id, invalid_username, invalid_user_id, invalid_tool_type, invalid_format, invalid_params, missing_query, missing_ids, missing_params, too_many_ids, unsupported_field, and invalid_coverage_cursor.

401 authentication

Retry: no. Check x-api-key, regenerate revoked keys, or re-authenticate the connected X account. Covers unauthenticated and x_auth_failure.

402 billing and credits

Retry: no. Read payment_options, then get explicit user confirmation. Covers no_subscription, subscription_inactive, payment_failed, no_credits, and insufficient_credits.

403 permissions and account health

Retry: no. Delete an extra key, check billing status, use a participating DM account, re-authenticate the X account, or resolve account health on x.com. Covers api_key_limit_reached, dm_not_permitted, account_needs_reauth, and account_restricted.

404 missing resource

Retry: no. Verify the resource ID, connected account, username, tweet ID, media, article, draft, or cached style. Covers not_found, account_not_found, user_not_found, tweet_not_found, no_media, article_not_found, draft_not_found, style_not_found, and no_cached_style.

409 or 410 cursor state

Busy cursor: follow Retry-After and retry once. Gone cursor: restart cursorless and deduplicate IDs.

422 write validation

Retry: no. Fix the account capability, target, content, DM permissions, or media URL before sending again. Covers x_account_feature_required, x_account_suspended, x_account_protected, x_duplicate_action, x_dm_not_allowed, x_target_not_found, x_content_too_long, x_rejected, and media_download_failed.

202 active write

Retry: no. Store the action and poll statusUrl while terminal is false. Follow Retry-After, pollAfterMs, and nextAction.

429 rate limit or cooldown

Retry: mixed. Retry rate_limit_exceeded and x_rate_limited after Retry-After or exponential backoff. Wait out login_cooldown via retryAfterMs. Do not retry x_daily_limit on the same X account for 24 hours.

500, 502, and 503 transient failures

Retry: yes for internal_error, x_api_rate_limited, x_api_unavailable and x_api_unauthorized. For writes, retry only when safeToRetry is true, using a new Idempotency-Key.

Common error codes

This section covers common recovery paths. The OpenAPI Error schema lists every public code. Default response.
Send xquik-api-contract: 2026-04-29 for a structured error object. Some responses also include message, reason, retryAfter, or retryAfterMs.
Request body, query, or path validation failed. Fix the request shape before retrying.

invalid_input

Request body failed validation. Check required fields, types, and enum values against the endpoint docs.

invalid_json

Request body is not valid JSON. Rebuild the body and send a parseable JSON object.

invalid_id

Path ID is not valid. Use the numeric string returned by the create or list endpoint.

invalid_tweet_url

Tweet URL is malformed. Use the full format https://x.com/user/status/ID.

invalid_tweet_id

Tweet ID is empty or malformed. Extract the final numeric status ID before calling tweet, media, or article endpoints.

invalid_username

Username or user path value is empty or invalid. Send a username without the @ prefix, or send a numeric user ID where supported.

invalid_user_id

User lookup input is invalid or does not resolve. Check the username or numeric user ID before retrying.

invalid_tool_type

Extraction tool type is not recognized. Use one of the 23 valid tool types from Create Extraction.

invalid_format

Export format is unsupported. Use csv, json, md, md-document, pdf, txt, or xlsx.

invalid_params

Export query parameters are invalid. Check the format and type values for that export endpoint.

missing_query

Required search query is missing. Add the q parameter before calling search or community endpoints.

missing_ids

Required multi-ID query is missing. Provide comma-separated numeric IDs in the ids parameter.

missing_params

Required query parameters are missing. Check the endpoint docs; follower checks require both source and target.

too_many_ids

Too many IDs were requested at once. Split requests into groups of 100 IDs or fewer.

unsupported_field

Request body contains a field this endpoint does not accept. For tweet posts, send public media URLs in media, not uploaded media IDs.

invalid_coverage_cursor

Cursor is malformed. Restart without it and deduplicate stored IDs.
Missing or invalid credentials. Check your API key or session.

unauthenticated

API key or bearer token is missing or invalid. Send x-api-key or regenerate a revoked key.

x_auth_failure

Connected X account session expired or was invalidated. Re-authenticate the account from the dashboard.
Non-MPP paid reads return 401 with WWW-Authenticate: Bearer and a guest wallet action. This is not a Payment challenge. Authenticate or get confirmation before calling the action.
A 402 creates no checkout. Account and OAuth responses advertise account billing actions. Guest responses advertise only POST /api/v1/guest-wallets/topups. Direct MPP responses include a Payment challenge and guest option. Get confirmation before calling any action.

no_subscription

No plan. Check credits, then top up or subscribe.

subscription_inactive

Plan inactive. Remaining credits work. Top up or reactivate on the billing page.

payment_failed

Payment processing failed. Update the payment method from the dashboard.

no_credits

No credit balance is available. Check balance with Get Account, then use Top Up Credits after confirmation.

insufficient_credits

Balance is below the required operation cost. Account callers can check Get Account. Guest callers can check Guest Wallet Status. Use only the payment action advertised for that credential.
Action not allowed under current plan or limits.

api_key_limit_reached

The account already has 100 active API keys. Revoke an active key before creating another.

dm_not_permitted

DM history requires a connected account that participates in the conversation. Use a participating account or reconnect it from the dashboard.

account_needs_reauth

Connected X account session needs re-authentication. Reconnect the account from the dashboard, then retry.

account_restricted

Connected X account is locked, suspended, recovering, or temporarily blocked. Resolve account health on x.com or wait before retrying.
The requested resource does not exist, is unavailable to this API key, or is not the expected X object type.

not_found

Generic resource lookup failed. Verify the ID belongs to your account and has not been deleted.

account_not_found

Connected X account was not found for this user. Call List X Accounts and use a valid connected account.

user_not_found

X username or numeric user ID does not resolve. Confirm the username with the user or try a different handle.

tweet_not_found

Tweet ID does not resolve. Check the numeric tweet ID; the tweet may have been deleted.

no_media

Tweet exists but has no downloadable media attachments. Use a tweet that contains media.

article_not_found

Tweet ID is valid but is not an X Article. Ask for an X Article URL or use a normal tweet or thread endpoint.

draft_not_found

Draft ID does not exist. Verify the draft ID or create a new draft.

style_not_found

Writing style ID was not found. Analyze tweets first with Analyze Style.

no_cached_style

No cached writing style exists for username lookup. Analyze tweets first with Analyze Style.
Reuse duplicate monitors. Recover cursors by status and error code.

monitor_already_exists

Duplicate account or keyword monitor. List existing monitors, reuse the monitor ID, or update event types with Update Monitor or Update Keyword Monitor.

coverage_cursor_unavailable

Follow the exact Retry-After seconds. Retry the same cursor once.

coverage_cursor_gone

No Retry-After. Restart cursorless and deduplicate IDs.
Write validation failed. Change the account, target, content, DM permission, or media input before retrying.

x_account_feature_required

Account capability is missing. Use an account with the required capability or adjust the request.

x_account_suspended

Connected X account is suspended or restricted. Resolve account status on x.com before sending more writes from it.

x_account_protected

Target account is protected. Request access first or choose a target account that the connected account can interact with.

x_duplicate_action

Operation is already complete. Do not retry unchanged; check the target state before sending anything again.

x_dm_not_allowed

Recipient does not accept DMs from this account. Use a permitted connected account or ask the recipient to allow messages.

x_target_not_found

Tweet or user target does not exist. Verify the ID or username before sending another request.

x_content_too_long

Content exceeds the character limit. Shorten the text or use an account that supports the requested content length.

x_rejected

X rejected the write without a specific reason. Change the request. Retry only when the durable action marks it safe.

media_download_failed

Public media URL could not be downloaded. Fix the HTTPS URL or pass the file via multipart/form-data. Do not retry the same URL.
The durable write remains active. Its status is accepted, dispatching, or pending_confirmation.

Poll

Store id, request.hash, account, target, and billing. Poll statusUrl after Retry-After or pollAfterMs.

Recovery

Stop when terminal is true. Retry only when safeToRetry is true, using a new key. Verify the result when nextAction.type is verify_result.
Request rate exceeded. See Rate Limits for tier details.

rate_limit_exceeded

Xquik tier or action limit was reached. Wait the Retry-After seconds from the response; JSON also includes retryAfter when available.

login_cooldown

A recent login attempt triggered cooldown. Wait retryAfterMs or the Retry-After header before reconnecting or reauthenticating.

x_rate_limited

X throttled the write. Follow Retry-After, then retry with backoff.

x_daily_limit

Connected X account reached its daily posting limit. Wait 24 hours before retrying that account, or use another connected account.
Transient failures. Retry with exponential backoff (max 3 attempts).

internal_error

Server error. Retry with backoff and contact support if it persists.

x_api_rate_limited

Read service rate limited. Retry in a few minutes.

x_api_unavailable

Read service temporarily unavailable or busy. Respect Retry-After when present, otherwise retry with backoff.

x_api_unauthorized

Read service authentication failed. Retry later and contact support if it persists.

x_write_failed

Write action failed unexpectedly. Follow safeToRetry and nextAction. Contact support if the action remains unsafe to retry.

x_write_ambiguous

Completion could not be confirmed. Poll the durable action, then verify the result before sending anything again.

x_transient_error

Temporary write failure. Retry only when safeToRetry is true.

Write lifecycle recovery

Every write can return a durable action. Inspect the JSON lifecycle fields before generic success or error handling.
1

Store the action

Store id, status, request.hash, account, target, billing, and statusUrl.
2

Poll the write action

Poll statusUrl while terminal is false. Respect Retry-After and pollAfterMs.
3

Persist the outcome

Store result and settled billing after terminal becomes true.
4

Follow retry safety

Retry only when safeToRetry is true, using a new Idempotency-Key. Verify the result when nextAction.type is verify_result.

Retry with exponential backoff

For reads, retry only on 429 and 5xx responses. Use Retry-After, then exponential backoff with jitter. For writes, follow the durable action’s safeToRetry and nextAction fields instead. Formula. delay = baseDelay * 2^attempt + random(0, jitter)

Rate limit handling

When a request is rate limited, Xquik returns 429 Too Many Requests with a Retry-After header. Some JSON bodies also include retryAfter in seconds or retryAfterMs in milliseconds for login cooldowns.

HTTP status

429 Too Many Requests means the request is rate limited or waiting on an account cooldown.

Retry-After header

The Retry-After header gives seconds to wait before sending the same request again.
1

Check the status

Branch on response.status === 429 before normal success handling.
2

Prefer the header

Parse Retry-After as seconds. If it is missing, read retryAfter or retryAfterMs from the JSON body.
3

Wait the full duration

Do not send another request for the same operation until the wait expires.
4

Back off after another 429

If the same request returns another 429, apply exponential backoff and stop after 3 attempts.

Best practices

Do not retry a 4xx response unchanged. Fix authentication, billing, permissions, or input first. Retry 429 and 5xx only as described above.
Log the status and error code. Never log credentials or private payloads.
Reuse monitor_already_exists. For a busy cursor, follow Retry-After and retry once.
Set a bounded client timeout. Use status endpoints for long-running jobs.
Creating a monitor for the same username returns 409. Deleting a non-existent resource returns 404. Both are safe to retry.

Rate limits

Detailed rate limit tiers and client-side rate limiting.

API overview

Base URL, authentication, and API conventions.