Checking registration availability…

Error reference

Every error code the SocialCannon API returns in its JSON responses, where it happens, what it means and the safe next action. Browser OAuth connect redirects report their own errors on the page they return to.

An error response looks like { "success": false, "error": "...", "code": "...", "details": { ... } }. Match on code, not on the error text, which is written for people and can change. Some responses also carry data with the post’s stable ID, limit for plan limits, or a Retry-After header.

Before you retry

For every write retry, including after fixing authentication, permissions or rate limits: Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

  1. Keep the IDs a response returns. On post endpoints data.id (or data.postId from retry) is the post’s stable ID; on A/B tests data.id is the test and each variant’s post is data.variants[].postId; auto-schedule lists its items in data.
  2. If the response has data.reconciliationRequired or data.providerPublished, or the code is IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, PUBLISH_OUTCOME_UNCERTAIN, PROVIDER_RECONCILIATION_REQUIRED or ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, do not send it as a new post or under a new key. If you cannot read the post (posts:read), contact support rather than replacing it. For a create, read the outcome with GET /api/v1/posts/idempotency and the original Idempotency-Key, or with GET /api/v1/posts/{id}; repeating the identical request with the same key is also safe (a create sent without a key must never be repeated), except after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, which must not be repeated until support reconciles the account, and except that a recovery verification is repeated only through POST /api/v1/accounts/{id}/recovery, never as a plain create. For an A/B test, read GET /api/v1/ab-tests/{id} or repeat it with the same key, except after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, which must not be repeated until support reconciles the account. From the retry endpoint, do not retry such a result again; read the post.
  3. Retry only when details.retryable is true or the entry below says it is safe. On endpoints that take an Idempotency-Key (posts, account recovery verification, A/B tests, auto-schedule, and API client provisioning with the same client_secret), repeat the request with the same key: a replay with the same key never publishes twice.
  4. Repurpose takes no Idempotency-Key. A reconciliation code stops retries until support resolves it. Never resend the whole request after any target published or may have published, even when none reports success. Check each result: providerPublished or reconciliationRequired, a published post status, platformPostId, platformPostUrl or a recovery object means stop and reconcile, not retry. Before retrying a missing target, follow the full repurpose recovery rule to identify any saved post or draft, including a draft whose acknowledgement was lost. Retry a failed post or delete it before replacing that target, never both; a draft cannot be retried. Any required deletion must succeed first. If the state is unclear, scopes are missing or deletion fails, contact support instead of retrying. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. Full repurpose recovery rule.
  5. A new key starts a new operation (a new post, test or schedule). Use one only after the original is confirmed not published.

Repurpose recovery

First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

Request and client

The request itself was refused before any work started.

INVALID_IDEMPOTENCY_KEY

HTTP status of a failed response: 400

Where: POST /api/v1/posts, GET /api/v1/posts/idempotency, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
The Idempotency-Key header is not 8 to 128 printable ASCII characters without spaces. The lookup endpoint also returns it when the header is missing. API client provisioning is different: it needs a canonical lowercase UUIDv4.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
From POST /api/v1/posts: nothing was created, so fix the key and send the request again. From GET /api/v1/posts/idempotency: the lookup could not run, which says nothing about the original request; fix the key and look up again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

IDEMPOTENCY_KEY_REQUIRED

HTTP status of a failed response: 400

Where: POST /api/v1/ab-tests, POST /api/v1/posts/auto-schedule

What it means
These endpoints always need an Idempotency-Key header (8 to 128 printable ASCII characters, no spaces).
What to do
Create one key for this operation, store it, and send it. Reuse the same key for every retry of the same operation. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

ENDPOINT_REMOVED

HTTP status of a failed response: 410

Where: POST /api/v1/media/upload, GET /api/v1/media/upload

What it means
The old upload endpoint, which buffered files through SocialCannon, was removed.
What to do
Upload in three steps: POST /api/v1/media/upload-init, PUT the bytes to the returned signed URL with the exact requiredHeaders, then POST /api/v1/media/upload-complete.

TRUSTED_CLIENT_PROVISIONING_FORBIDDEN

HTTP status of a failed response: 403

Where: POST /api/v1/auth/clients

What it means
The calling API client is not currently allowed to create API sub-clients.
What to do
Do not retry. Ask SocialCannon support to review this client's provisioning access.

TENANT_DELETING

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/media/upload-init, POST /api/v1/media/upload-complete, POST /api/v1/accounts/{id}/recovery

What it means
This SocialCannon account is being deleted, so it no longer accepts posts, uploads or checks.
What to do
Stop sending work for this account. The response sets details.retryable to false where details are present.

Plan and usage limits

A plan feature or usage limit blocked the request, or one part of it.

LIMIT_EXCEEDED

HTTP status of a failed response: 403

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, PATCH /api/v1/posts/{id}, POST /api/v1/posts/auto-schedule, POST /api/v1/links/generate, GET /api/v1/accounts/{id}/timing, POST /api/v1/timing/optimal-slots, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
A plan limit or plan feature blocks the affected operation or target. When present, limit.type says which: platform, twitter_posts_per_period, repurpose_per_period, thread_items, tracked_links, concurrent_ab_tests or sandbox_lifetime. Timing features and repurpose target counts return it without a limit object. posts_per_period, scheduled_posts, media_uploads_per_period are not capped on any current plan.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
A single create, thread or repurpose target refused this way published nothing. An A/B test may already have published earlier variants, and auto-schedule may already have scheduled earlier items, before the limit was reached: read data, do not use a new key, and resume with the same Idempotency-Key once the limit allows. Fix the limit named by limit.type: twitter_posts_per_period, repurpose_per_period reset next billing period or rise with an upgrade (on Enterprise, contact sales@socialcannon.app for a higher cap); tracked_links needs an upgrade (the API cannot remove links); concurrent_ab_tests needs a running test completed or cancelled; platform and the timing features need a plan that includes them; thread_items is capped at 25 on every paid plan, so a paid-plan caller must reduce the thread to at most that many items; only the Free cap is raised by upgrading; sandbox_lifetime needs a real account; a repurpose target-count refusal (no limit object) needs fewer targetPlatforms or an upgrade. For PATCH, link generation and the timing endpoints, simply send the same request again once the limit allows. Then: a fresh create refused this way has no Idempotency-Key binding, so send the create again, with the request corrected where the limit is about content (a thread of more than the item cap, or a repurpose target count the plan does not allow) (with the same key, if you sent one; threads take no key). If the response carries data.id and details.action "upgrade_plan", the post was saved as failed: retry it with POST /api/v1/posts/{id}/retry. From the retry endpoint itself, call it again; the original create cannot be repeated. For an A/B test or auto-schedule, read data, then repeat the request with the same Idempotency-Key to resume. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

TIER_FEATURE_DISABLED

HTTP status of a failed response: 403

Where: GET /api/v1/posts/{id}/analytics, GET /api/v1/analytics/summary, POST /api/v1/analytics/refresh, POST /api/v1/engagements/{id}/reply

What it means
Analytics or engagement replies are not included in the current plan.
What to do
Do not retry. Upgrade to a plan that includes the feature.

PLAN_LOOKUP_RETRYABLE

HTTP status of a failed response: 503

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, PATCH /api/v1/posts/{id}, POST /api/v1/posts/auto-schedule, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
SocialCannon could not verify the plan just now. Where details is present, details.retryable is true.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Retry later. For a keyed operation, including A/B tests and auto-schedule, keep the same Idempotency-Key and do not create a replacement post. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

Connected accounts

The social account cannot be used until its access or state is fixed.

ACCOUNT_RECONNECT_REQUIRED

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, DELETE /api/v1/posts/{id}, GET /api/v1/posts/{id}/engagements, POST /api/v1/engagements/{id}/reply, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
The account's access expired or was revoked, a required permission is missing (a top-level missingScopes lists it), or Meta put the account behind a security check. Where details is present, details.retryable is false.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Do not retry. The account owner reconnects the same network account (the same Page, profile or handle) in the dashboard under Accounts; if a different account would be connected, do not retry the old post, because it would publish to a different audience. If details.action is "complete_meta_security_check_then_reconnect", they first complete Meta's check on facebook.com. For an engagement reply, check the comment thread before sending it again; do not blindly resend a reply. For an engagement read, repeat that read. For a deletion, retry the deletion. For a fresh post, thread or A/B-test create with no data.id, resend the same request after access is restored; keep the original Idempotency-Key for a keyed post or A/B test (threads take no key). For repurpose, follow the target-specific instructions above, resending only missing targets. For saved posts, follow the rules below. From POST /api/v1/posts/{id}/retry (data.postId is the existing post), fix the cause and call the same retry endpoint again; do not resend the original create. If a POST /api/v1/posts response carries data.id, the post was saved as failed: after reconnecting, retry it with POST /api/v1/posts/{id}/retry instead of resending the create. From an A/B test, data.id is the test: if data.status is active or completed, its variants are already durable, so do not create a replacement; while data.status is provisioning, repeat the same request with the same Idempotency-Key; once it is failed or canceled, the key cannot resume it, so before reusing its variants' content in a replacement under a new key (and never reuse the content of a variant the owner published as the account recovery check post), delete with DELETE /api/v1/posts/{id} every variant post in data.variants that is not already deleted (provisioned, scheduled, awaiting_account, publishing, published, reconciliation_required or failed): a failed one can still be retried, and a published one would be duplicated by a replacement with the same content. If any of those deletions cannot be completed (for example PLATFORM_DELETE_UNSUPPORTED, PUBLISH_IN_PROGRESS or a reconciliation code), do not create the replacement test; contact support. A failed thread cannot be retried: check which items are live before creating a new thread, and do not reuse the content of an item the owner published as the account recovery check post. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

ACCOUNT_ACTION_REQUIRED

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, PATCH /api/v1/posts/{id}, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
With details (publishing endpoints): the account has an open restriction, such as an identity check, missing Page permissions, a platform review or an earlier publication whose outcome is unresolved. details.action names the fix and details.recoveryUrl where to make it. Without details (PATCH /api/v1/posts/{id} on content held during a restriction): the new schedule is not allowed yet, and the message says why, for example a time less than five minutes ahead, posts closer than five minutes apart, or access not yet restored.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Do not retry publishing until the cause is fixed. Without details, change the schedule as the message says, or restore access first, then send the update again; if the message says an earlier publication is unresolved, restoring access does not settle it, so contact support before rescheduling. With details, the owner follows details.action. When that action ends in verify, publishing is verified from the dashboard or with POST /api/v1/accounts/{id}/recovery, which publishes one real post that you choose, so get the owner's approval first; if that verification post carries the content this request was trying to publish, it is now live, so do not also send this request again or retry its saved post (delete a saved failed post with no live markers instead); otherwise apply the steps below once verification succeeds. Reconnect only the same network account (the same Page, profile or handle); if a different account would be connected, do not retry the old post. From POST /api/v1/posts/{id}/retry (data.postId is the existing post), fix the cause and call the same retry endpoint again; do not resend the original create. Once it is fixed, a request that returned no data.id saved nothing: send it again, but for a repurpose request send only the targets that are still missing, because other targets may already have published (with the same key for keyed creates and A/B tests; threads take no key). If a POST /api/v1/posts response carries data.id, the post was saved as failed: once access is restored, retry it with POST /api/v1/posts/{id}/retry. From an A/B test, data.id is the test: if data.status is active or completed, its variants are already durable, so do not create a replacement; while data.status is provisioning, repeat the same request with the same Idempotency-Key; once it is failed or canceled, the key cannot resume it, so before reusing its variants' content in a replacement under a new key (and never reuse the content of a variant the owner published as the account recovery check post), delete with DELETE /api/v1/posts/{id} every variant post in data.variants that is not already deleted (provisioned, scheduled, awaiting_account, publishing, published, reconciliation_required or failed): a failed one can still be retried, and a published one would be duplicated by a replacement with the same content. If any of those deletions cannot be completed (for example PLATFORM_DELETE_UNSUPPORTED, PUBLISH_IN_PROGRESS or a reconciliation code), do not create the replacement test; contact support. A failed thread cannot be retried: check which items are live before creating a new thread, and do not reuse the content of an item the owner published as the account recovery check post. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

ACCOUNT_REFRESH_RETRYABLE

HTTP status of a failed response: 503

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, DELETE /api/v1/posts/{id}, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
SocialCannon could not renew the account's access for a temporary reason, so this attempt for the affected post or target did not reach the network unless the response also has reconciliationRequired or providerPublished. In repurpose, other targets may have published. From an A/B test, earlier variants may already be published even without those flags, and data.variants in this response may not show it yet: read GET /api/v1/ab-tests/{id} before judging what is live, and resume only with the original key while it can be resumed.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
First: if the response also has reconciliationRequired or providerPublished, the post may be live: read it and do not retry. Otherwise: Retry after the Retry-After delay when one is given. For a keyed create, repeat the same request with the same Idempotency-Key. For an A/B test, data.id is the test: while data.status is provisioning, repeat the same request with the same Idempotency-Key; if it is active or completed, its variants are durable, so do not create a replacement; once data.status is failed or canceled, the key cannot resume it, so follow INSUFFICIENT_ELIGIBLE_VARIANTS (before reusing its variants' content, and never reusing the content of a variant the owner published as the account recovery check post, delete every variant post that is not already deleted) before any replacement under a new key. From POST /api/v1/posts/{id}/retry (data.postId), first read GET /api/v1/posts/{id}. Retry that same post only if it is failed with no platformPostId, platformPostUrl or recovery object. If any such marker exists, the post is not failed, or it cannot be read, do not retry; wait for reconciliation or contact support. For a thread with data.id, the failed thread cannot be retried: create a new thread only if the response has neither reconciliationRequired nor providerPublished and no item is live; otherwise read it and contact support. For DELETE /api/v1/posts/{id}, retry the deletion after the delay. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

ACCOUNT_REFRESH_RECONCILIATION_REQUIRED

HTTP status of a failed response: 503

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
A credential refresh may have changed the account's access, and its result is unknown. details.retryable is false.
If this came from POST /api/v1/posts/repurpose
From repurpose: as the whole response, no target was processed, but hold the request until the account is reconciled, and then send only the targets that are still missing (never the whole request if an earlier request may have published some). As one target's entry in data.results: do not retry that target until then either, and never resend the whole request, because other targets may already have published. Once support has reconciled the account, a target entry with a postId was saved (and if the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again): read it. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again; if it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it before sending that target again, never both; if it is a draft, it cannot be retried, so delete it before sending that target again; in any other state, or if the deletion fails, contact support. A target entry without a postId was refused before anything was saved, so send only that target again, unless the owner already published that content as the account recovery check post, in which case it is live and must not be sent again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Do not retry publishing, and do not reconnect yet: an earlier operation on the account is unresolved, and changing its credentials can interfere with reconciling it. Contact support; reconnect only once that operation is reconciled. Do not create a replacement post or use a new key in the meantime. Once support has reconciled the account, recover by endpoint. From POST /api/v1/ab-tests, data is the test and data.id is the test ID, never a post ID: read it with GET /api/v1/ab-tests/{id} if you need its state, and to continue, send the original request again with its original Idempotency-Key, which resumes the same test and variants without duplicating posts while data.status is provisioning; if it is active or completed, do not create a replacement; once data.status is failed or canceled, the key cannot resume it, so follow INSUFFICIENT_ELIGIBLE_VARIANTS (before reusing its variants' content, and never reusing the content of a variant the owner published as the account recovery check post, delete every variant post that is not already deleted) before any replacement under a new key. From POST /api/v1/posts with data.id, the post was saved but its outcome may still be open: read it with GET /api/v1/posts/{id} (and, if you sent an Idempotency-Key, GET /api/v1/posts/idempotency with it), and retry it with POST /api/v1/posts/{id}/retry only once it is failed with no live markers and no recovery object, and for a keyed create its outcome is not_published; while it is unresolved, wait for support, keep any original key, and never resend the create. From the retry endpoint (data.postId): read the post and, only if it is failed with no live markers, call the same retry endpoint again. From POST /api/v1/posts without data.id: if the request carried an Idempotency-Key, send the original request again with that key, which resumes the saved draft if this was a resumed create and is otherwise still unbound; never switch to a new key. If it carried no key, nothing was saved, so send the create again once the account is reconciled. Either way, if this came from a repurpose request, send only the targets that are still missing and never the whole request, because other targets may already have published. From POST /api/v1/posts/thread, which takes no key: with data.id, the thread was saved and cannot be retried, so read it and check its items before creating a new thread; if the response also has reconciliationRequired or providerPublished, some items may be live, so do not create a new thread and contact support instead; without data.id, nothing was saved, so send the thread again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

ACCOUNT_LOOKUP_RETRYABLE

HTTP status of a failed response: 503

Where: POST /api/v1/posts/repurpose

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
SocialCannon could not read a target account just now. As the whole response, it means no target was processed; as one entry in data.results, other targets may have published.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
What to do
Retry later. If it is the whole response, send the request again, but only if no earlier attempt of it published any target; otherwise send only the targets that are still missing. If it is one target's result, retry only that target, never the whole request. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

ACCOUNT_NOT_FOUND

HTTP status of a failed response: 404

Where: POST /api/v1/media/upload-init

What it means
accountId does not name one of this client's connected accounts.
What to do
List accounts with GET /api/v1/accounts and use a current ID.

ACCOUNT_INACTIVE

HTTP status of a failed response: 409

Where: POST /api/v1/media/upload-init

What it means
The connected account is disconnected.
What to do
Reconnect the account, then start the upload again.

ACCOUNT_DISCONNECTED

HTTP status of a failed response: 409

Where: POST /api/v1/accounts/{id}/recovery

What it means
The account is disconnected, so its publishing access cannot be checked.
What to do
Reconnect the account first.

ACCOUNT_CONNECTION_CHECK_UNAVAILABLE

HTTP status of a failed response: 503

Where: POST /api/v1/accounts/{id}/recovery

What it means
The read-only connection check could not complete. details.publishingVerified is false.
What to do
Try the check again later.

ACCOUNT_RECOVERY_NOT_READY

HTTP status of a failed response: 409

Where: POST /api/v1/accounts/{id}/recovery

What it means
From recheck_connection: the account was not found or is disconnected. From verify_publishing: the account's recovery changed, is already being checked, or an earlier network operation is unresolved.
What to do
From recheck_connection, reconnect the exact account, then check again. From verify_publishing, reload the account and review its recovery status in the dashboard, and do not send another verification publication.

PROVIDER_MUTATION_IN_PROGRESS

HTTP status of a failed response: 409

Where: DELETE /api/v1/accounts/{id}

What it means
A publish or delete on this account is waiting for a recorded outcome. data.reconciliationRequired is true.
What to do
Wait for the operation to settle, or contact support, before disconnecting the account.

Media upload and preparation

A file could not be accepted, fetched or prepared for publishing.

INVALID_REQUEST

HTTP status of a failed response: 400

Where: POST /api/v1/media/upload-init

What it means
The request is missing a field it needs: filename, contentType, a positive size, or a usable accountId (an empty or non-string ID) when the destination policy is resolved.
What to do
Fix the field the message names and send the upload again. For accountId, send a connected account's ID, or leave it out to use the general per-file limit. For filename, contentType or size, send them with the values the upload-init request expects.

INVALID_POST_TYPE

HTTP status of a failed response: 400

Where: POST /api/v1/media/upload-init

What it means
postType must be one of: feed, reel, story, short, carousel, thread.
What to do
Send the post type the file will be published as. SocialCannon never falls back to another type.

UNSUPPORTED_MEDIA

HTTP status of a failed response: 400

Where: POST /api/v1/media/upload-init

What it means
This file type cannot be published to that account and post type, or the account is the sandbox, which stores no media at all.
What to do
For a real account, use an accepted format from the Media Upload Limits table in the API reference. For the sandbox, no upload works: test without media, or upload for a real account.

MEDIA_LIMIT_EXCEEDED

HTTP status of a failed response: 400

Where: POST /api/v1/media/upload-init

What it means
The file is larger than the destination's per-file limit, or than the general limit when no accountId is sent. No upload URL was issued.
What to do
Use a smaller file. The Media Upload Limits table lists each limit.

MEDIA_UPLOAD_AUTHORITY_UNAVAILABLE

HTTP status of a failed response: 409

Where: POST /api/v1/media/upload-init

What it means
This API client no longer accepts new media uploads.
What to do
Do not retry. Contact support.

MEDIA_INACCESSIBLE

HTTP status of a failed response: 400

Where: POST /api/v1/posts, POST /api/v1/ab-tests, POST /api/v1/posts/{id}/retry, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
A media URL could not be fetched: it is not public, has expired or was deleted. For a keyed POST /api/v1/posts that carries data.id, the post was saved as failed and its key is settled.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
First: if the response also has reconciliationRequired or providerPublished, the post may be live: read it and do not retry. Otherwise: If a post was saved (data.id, or the post ID used at the retry endpoint), read it first with GET /api/v1/posts/{id} (needs posts:read). If it is published, has a platformPostId, platformPostUrl or recovery object, is not failed, or cannot be read, do not create a replacement; contact support if it cannot be settled. Only for a failed post with no live markers: if its stored media is reachable again, retry that post with POST /api/v1/posts/{id}/retry; otherwise delete it with DELETE /api/v1/posts/{id} and, only after deletion succeeds, upload the media again and create a new post with a new key. Retrying cannot replace stored media, and a keyed create with data.id has a settled key: repeating that create will not publish. For an immediate create with no saved post, make the file publicly reachable or upload it again, then send the corrected request, retaining any original key. A scheduled post must use media uploaded through SocialCannon. For an A/B test, this media check runs before the test is created, so nothing is bound to the key yet: fix the media and send the request with the same key. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

MEDIA_STORAGE_UNAVAILABLE

HTTP status of a failed response: 503

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/ab-tests, PATCH /api/v1/posts/{id}, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
Storage could not prepare the media in time, so the affected post or target did not publish. In repurpose, other targets may have published; this does not mean the whole request published nothing.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Retry later. For a keyed create or an A/B test, use the same Idempotency-Key. For a thread, send the same thread request again after the delay; for PATCH, send the same update again after the delay. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

SCHEDULED_MEDIA_EXTERNAL_REQUIRES_UPLOAD

HTTP status of a failed response: 400

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/ab-tests, PATCH /api/v1/posts/{id}

What it means
Scheduled posts cannot point at media hosted elsewhere, because that file could change or disappear before publishing.
What to do
Upload the file through /api/v1/media/upload-init and upload-complete, then create the scheduled post with the returned publicUrl. If a keyed POST /api/v1/posts response carries data.id, that key is settled and repeating it will not create the post: read the failed post, and if it has no recovery object, platformPostId or platformPostUrl, delete it (DELETE /api/v1/posts/{id}) and create a new post with a new key (do not use the retry endpoint to schedule it). For an A/B test, this check runs before the test is created, so nothing was provisioned and the key is still unbound: fix the media and send the request again. For a refused thread create (nothing was saved), send it again with the uploaded media. From PATCH: an update cannot replace a post's media. First read the post with GET /api/v1/posts/{id} (needs posts:read; deleting needs posts:delete, and without both, contact support instead): if it has an accountHold, a recovery object, a platformPostId or a platformPostUrl, do not replace it; contact support. Otherwise delete it (DELETE /api/v1/posts/{id}), and only after the deletion succeeds create a replacement with uploaded media; never create a second post or thread while the original is still scheduled. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULED_MEDIA_NOT_OWNED

HTTP status of a failed response: 400, 403

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/ab-tests, PATCH /api/v1/posts/{id}, POST /api/v1/posts/{id}/retry

What it means
The media was not uploaded by this API client, or its ownership cannot be verified.
What to do
For a create, upload the file with this client's own credentials and use that publicUrl. If a keyed POST /api/v1/posts response carries data.id, that key is settled and repeating it will not create the post: read the failed post, and if it has no recovery object, platformPostId or platformPostUrl, delete it (DELETE /api/v1/posts/{id}) and create a new post with a new key (do not use the retry endpoint to schedule it). From POST /api/v1/posts/{id}/retry: first read the failed post with GET /api/v1/posts/{id} (needs posts:read); if it has a platformPostId, a platformPostUrl or a recovery object (SocialCannon shows one whenever an earlier attempt is unresolved), an earlier attempt may be live, so do not create a replacement and contact support. If you cannot read the post, do not create a replacement either. Only if it has neither, delete it (DELETE /api/v1/posts/{id}), upload the media again and create a new post; retrying cannot replace a failed post's media. For an A/B test, this check runs before the test is created, so nothing was provisioned and the key is still unbound: fix the media and send the request again. For a refused thread create (nothing was saved), send it again with the uploaded media. From PATCH: an update cannot replace a post's media. First read the post with GET /api/v1/posts/{id} (needs posts:read; deleting needs posts:delete, and without both, contact support instead): if it has an accountHold, a recovery object, a platformPostId or a platformPostUrl, do not replace it; contact support. Otherwise delete it (DELETE /api/v1/posts/{id}), and only after the deletion succeeds create a replacement with uploaded media; never create a second post or thread while the original is still scheduled. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULED_MEDIA_UNAVAILABLE

HTTP status of a failed response: 400

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/ab-tests, PATCH /api/v1/posts/{id}, POST /api/v1/posts/{id}/retry

What it means
The uploaded media is no longer available.
What to do
Upload the media again, then send the create with the new publicUrl. If a keyed POST /api/v1/posts response carries data.id, that key is settled and repeating it will not create the post: read the failed post, and if it has no recovery object, platformPostId or platformPostUrl, delete it (DELETE /api/v1/posts/{id}) and create a new post with a new key (do not use the retry endpoint to schedule it). From POST /api/v1/posts/{id}/retry: first read the failed post with GET /api/v1/posts/{id} (needs posts:read); if it has a platformPostId, a platformPostUrl or a recovery object (SocialCannon shows one whenever an earlier attempt is unresolved), an earlier attempt may be live, so do not create a replacement and contact support. If you cannot read the post, do not create a replacement either. Only if it has neither, delete it (DELETE /api/v1/posts/{id}), upload the media again and create a new post; retrying cannot replace a failed post's media. For an A/B test, this check runs before the test is created, so nothing was provisioned and the key is still unbound: fix the media and send the request again. For a refused thread create (nothing was saved), send it again with the uploaded media. From PATCH: an update cannot replace a post's media. First read the post with GET /api/v1/posts/{id} (needs posts:read; deleting needs posts:delete, and without both, contact support instead): if it has an accountHold, a recovery object, a platformPostId or a platformPostUrl, do not replace it; contact support. Otherwise delete it (DELETE /api/v1/posts/{id}), and only after the deletion succeeds create a replacement with uploaded media; never create a second post or thread while the original is still scheduled. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULED_MEDIA_STORAGE_FAILED

HTTP status of a failed response: 503

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/ab-tests, PATCH /api/v1/posts/{id}, POST /api/v1/posts/{id}/retry

What it means
The media could not be prepared or verified in storage just now.
What to do
Try again later. For POST /api/v1/posts, retain the original Idempotency-Key and read GET /api/v1/posts/idempotency with it before resending. If the response carries data.id, read that existing post with GET /api/v1/posts/{id}; do not create another post while its outcome is unresolved or it has a recovery object, platformPostId or platformPostUrl. If it is failed without those markers and the keyed outcome is not_published, either retry that post with POST /api/v1/posts/{id}/retry (the retry publishes immediately), or delete it with DELETE /api/v1/posts/{id} and, only after deletion succeeds, create a replacement with the wanted schedule and a new key; never do both. If it remains a draft or cannot be read, contact support before replacing it. With no data.id, repeat the unchanged create with the original key; without a key, nothing was saved by this preparation failure, so repeat the create. For thread or A/B-test creation this preparation check precedes saving the thread/test; repeat the request unchanged, keeping the original key for the A/B test. From PATCH, repeat the same update; from the retry endpoint, read the existing post first and repeat the same retry only once it is failed without a recovery object or provider identity. Do not replace a live or unresolved post. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULED_MEDIA_REQUIRES_REUPLOAD

HTTP status of a failed response: 400

Where: POST /api/v1/posts/{id}/retry

What it means
This older scheduled post's media is not pinned to an exact uploaded file, so it cannot be published safely.
What to do
From POST /api/v1/posts/{id}/retry: first read the failed post with GET /api/v1/posts/{id} (needs posts:read); if it has a platformPostId, a platformPostUrl or a recovery object (SocialCannon shows one whenever an earlier attempt is unresolved), an earlier attempt may be live, so do not create a replacement and contact support. If you cannot read the post, do not create a replacement either. Only if it has neither, delete it (DELETE /api/v1/posts/{id}), upload the media again and create a new post; retrying cannot replace a failed post's media. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULED_MEDIA_GRAPH_INVALID

HTTP status of a failed response: 400

Where: POST /api/v1/posts/{id}/retry

What it means
The post's stored media record is malformed.
What to do
From POST /api/v1/posts/{id}/retry: first read the failed post with GET /api/v1/posts/{id} (needs posts:read); if it has a platformPostId, a platformPostUrl or a recovery object (SocialCannon shows one whenever an earlier attempt is unresolved), an earlier attempt may be live, so do not create a replacement and contact support. If you cannot read the post, do not create a replacement either. Only if it has neither, delete it (DELETE /api/v1/posts/{id}), upload the media again and create a new post; retrying cannot replace a failed post's media. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULED_MEDIA_GRAPH_CONFLICT

HTTP status of a failed response: 409

Where: PATCH /api/v1/posts/{id}

What it means
The post's media changed while it was being prepared for scheduling.
What to do
Retry the update. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

Content, platform and scheduling

The post, the platform or the requested time does not fit the rules.

TIKTOK_PRIVACY_REQUIRED

HTTP status of a failed response: 400

Where: POST /api/v1/posts, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
TikTok posts need platformOptions.privacyLevel. TikTok does not allow a default. A/B tests refuse TikTok altogether with PLATFORM_UNSUPPORTED, because a variant cannot set its own privacy level.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Read the allowed values from GET /api/v1/accounts/{id}/tiktok/creator-info, ask the user to choose one, and send it. If a keyed POST /api/v1/posts response carries data.id, the key is settled and the retry endpoint cannot add a privacy level: delete it (DELETE /api/v1/posts/{id}) and create a new post with the chosen privacyLevel and a new Idempotency-Key, after confirming the failed post has no recovery object, platformPostId or platformPostUrl. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

SCHEDULE_EXPIRED

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/ab-tests, PATCH /api/v1/posts/{id}

What it means
While the request was being prepared, scheduledAt fell outside the allowed window: it is now in the past or more than 30 days ahead.
What to do
Choose a new time within the next 30 days and send the request again. If a keyed POST /api/v1/posts response carries data.id, that key is settled and repeating it will not create the post: read the failed post, and if it has no recovery object, platformPostId or platformPostUrl, delete it (DELETE /api/v1/posts/{id}) and create a new post with a new key (do not use the retry endpoint to schedule it). Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

PLATFORM_UNSUPPORTED

HTTP status of a failed response: 400

Where: POST /api/v1/ab-tests, GET /api/v1/posts/{id}/analytics, GET /api/v1/posts/{id}/engagements, POST /api/v1/engagements/{id}/reply

What it means
The platform does not support this feature through SocialCannon, or support is not available yet.
What to do
Do not retry. GET /api/v1/platforms lists what each platform supports.

INSTAGRAM_STORY_EXPIRED

HTTP status of a failed response: 400

Where: GET /api/v1/posts/{id}/analytics

Also returned with HTTP 200: GET /api/v1/posts/{id}/analytics, POST /api/v1/analytics/refresh

What it means
Instagram only reports Story analytics for 24 hours after publication. As an HTTP 400, it means no snapshot was collected in that time, so there are no figures for this Story.
What to do
Do not retry; live figures cannot be fetched again. When snapshots were collected, GET /api/v1/posts/{id}/analytics returns them with HTTP 200 instead.
Also appears in
HTTP 200 from GET /api/v1/posts/{id}/analytics as data.liveRefresh.code when snapshots exist, and as a skipped result in POST /api/v1/analytics/refresh.

Idempotency keys and replays

Answers to a repeated request. A replay never publishes a second time.

IDEMPOTENCY_CONFLICT

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/ab-tests, POST /api/v1/posts/auto-schedule, POST /api/v1/auth/clients, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
This Idempotency-Key was already used with a different request body.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
To repeat the original operation, send the original request unchanged; if its outcome is not_published, the key cannot publish it, so fix the cause and retry it with POST /api/v1/posts/{id}/retry. Before starting a different operation under a new key, settle the original first: for a post, read GET /api/v1/posts/idempotency with this key and wait until its outcome is published or not_published (a not_published post can still be retried with POST /api/v1/posts/{id}/retry if it is failed (a deleted post cannot be retried), so before using a new key, delete it with DELETE /api/v1/posts/{id} or decide to retry it instead, never both); a scheduled original can still publish, so delete it (DELETE /api/v1/posts/{id}) before using a new key if you are replacing it; a published original stays live, so before using a new key for a replacement, delete it as well, because the new operation publishes alongside it otherwise; and if the outcome stays unresolved, do not start a new key and contact support. Every deletion above must succeed before a new key is used: if it fails (for example PLATFORM_DELETE_UNSUPPORTED, a pending provider deletion or a reconciliation code), the original may still be live, so do not create the replacement and contact support; for an A/B test, read its result by repeating the original request. A test under a new key runs alongside the original, so if the new test is unrelated, leave the original and its posts alone. If the new test replaces the original, cancel the original test first while it is active or provisioning (DELETE /api/v1/ab-tests/{id}, which frees its active-test slot but leaves its variant posts live); a test that is already completed or failed cannot be cancelled, so skip the cancellation and delete its variant posts directly. Then delete with DELETE /api/v1/posts/{id} every variant post in data.variants that is not already deleted (provisioned, scheduled, awaiting_account, publishing, published, reconciliation_required or failed; use its postId and state). Leaving a variant out of the new test is not enough: a scheduled one still publishes and a failed one can still be retried. If any of those deletions cannot be completed (for example PLATFORM_DELETE_UNSUPPORTED, PUBLISH_IN_PROGRESS or a reconciliation code), do not create the replacement test; contact support; for auto-schedule, replay the original request unchanged to obtain its data: items in data.unscheduled are settled and a replay skips them, so schedule those separately if still wanted, and repeat the original until nothing is pending. Then remove any of its data.scheduled posts you do not want with DELETE /api/v1/posts/{id} before starting another. If you meant to change the original, a new key creates a second operation alongside it, so delete or cancel the original first. For POST /api/v1/auth/clients, replay the original request to get its result; provisioned sub-clients cannot be listed or cancelled through the API, so contact support before provisioning another. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

IDEMPOTENCY_IN_PROGRESS

HTTP status of a failed response: 409

Where: POST /api/v1/posts, PATCH /api/v1/posts/{id}, DELETE /api/v1/posts/{id}, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
From POST /api/v1/posts: the original request with this key is still being processed, and this replay did not publish again; data.id is the post's stable ID. From PATCH or DELETE: the keyed create behind this post is still running, so the post cannot be changed yet.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
For the create: wait, then read the outcome with GET /api/v1/posts/idempotency using the same key, or repeat the identical request with the same key. Never send it as a new post or under a new key. For PATCH or DELETE: wait, read the post with GET /api/v1/posts/{id}, then send the update or deletion again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

IDEMPOTENCY_OUTCOME_UNCERTAIN

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
The network may or may not have published this post, and SocialCannon could not confirm which. data.id identifies the post; a same-key replay also returns data.status and data.recovery (code PROVIDER_RECONCILIATION_REQUIRED). No replay publishes again. The first uncertain create answers with an uncoded HTTP 503 and data.reconciliationRequired, except after a failed account refresh, when it answers with this code and HTTP 409.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Do not resend and do not create a replacement under a new key. Read the post with GET /api/v1/posts/idempotency and the same key if you sent one, or with GET /api/v1/posts/{id} and data.id. Its outcome stays "unresolved" until SocialCannon reconciles it. Check the network itself or contact support before deciding anything else.

IDEMPOTENCY_NOT_FOUND

HTTP status of a failed response: 404

Where: GET /api/v1/posts/idempotency

What it means
No post is bound to that lookup key. This does not prove that an unkeyed attempt or an attempt under a different key saved or published nothing. With the original key, the request may never have reached SocialCannon or may have been refused before a post was created, for example by validation or a plan limit.
What to do
First confirm the lookup uses the original request's key. If it uses a different key, correct only the lookup header to the original key and look up again. If the original request was unkeyed, never add a key or resend it on the basis of this 404; read any known post ID, check the network and contact support instead. If the original request may still be running, wait and look up again. Only once you confirm the original request never arrived or was refused before anything was saved or published (for example invalid input or a plan limit), fix the cause and send it with the same original key. A 404 lookup alone does not prove that an earlier attempt never reached the network, so if such an attempt may have happened, contact support or read the post instead of sending the request again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

IDEMPOTENT_POST_FAILED

HTTP status of a failed response: 400, 403, 404, 409, 410, 413, 422

Where: POST /api/v1/posts, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
The original request with this key failed, or its post was deleted, and no more specific recovery applies. This replay did not publish.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Read the post (data.id) for its failureReason. Repeating this key will never publish. If it is failed (not deleted), it may still be retryable with POST /api/v1/posts/{id}/retry: retry it or delete it and replace it, never both; a deleted post cannot be retried. Create a new post with a new key only after confirming the original is not live: it has no recovery object, no platformPostId and no platformPostUrl, or it was deleted and its network post is confirmed removed (no recovery object). Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

Publishing results

What happened when SocialCannon tried to publish, and what is safe next.

MEDIA_TOO_LARGE

HTTP status of a failed response: 413

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
A file is over this publishing route's size limit, found before anything reached the network. details.maxBytes gives the limit when it is known. No post was published.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
First: if the response also has reconciliationRequired or providerPublished, the post may be live: read it and do not retry. Otherwise: If a failed post was saved (data.id, or data.postId from the retry endpoint), read it first: if it has a platformPostId, a platformPostUrl or a recovery object, keep it, do not create a replacement, and contact support. Otherwise delete it (DELETE /api/v1/posts/{id}), then create a new post with smaller media and a new Idempotency-Key. For a thread, create a new thread with smaller media; threads take no key. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

POST_DEFINITIVELY_REJECTED

HTTP status of a failed response: 422

Where: POST /api/v1/posts, POST /api/v1/posts/{id}/retry, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
The publish was rejected before it took effect. No post exists on the network.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
If details.action is "edit_media_or_destination", fix the media or destination. If the response carries data.id or data.postId, read that failed post first: if it has a platformPostId, a platformPostUrl or a recovery object, keep it, do not create a replacement, and contact support; otherwise delete it (DELETE /api/v1/posts/{id}). Then create a new post with a new Idempotency-Key (the retry endpoint cannot change media or destination). If it is "contact_support", the stored credentials could not be read; contact support, because editing the post will not help. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

POST_SETTLED_FAILED_RETRY_REQUIRED

HTTP status of a failed response: 409

Where: POST /api/v1/posts, POST /api/v1/posts/{id}/retry, POST /api/v1/accounts/{id}/recovery (verify_publishing)

What it means
Nothing was published in this attempt, and the post is saved as failed. A keyed create replayed with the same key will not publish it; an unkeyed create sent again would create a second post. details.action may name the cause, such as wait_for_publishing_limit, review_account_restriction or repair_permissions.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
Resolve the cause in the message, then call POST /api/v1/posts/{id}/retry (details.retryEndpoint) for the saved post. Do not resend the create, keyed or not. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

POST_SETTLED_THREAD_NO_POST

HTTP status of a failed response: 409

Where: POST /api/v1/posts/thread

What it means
No part of the thread was published, and the failure is recorded. details.action names the remedy.
What to do
If details.action is "contact_support", the stored credentials could not be read: contact support, because a new thread will fail the same way. Otherwise resolve the cause the message names, then create a new thread. Failed threads cannot be retried. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

PUBLISH_CAPACITY_RETRYABLE

HTTP status of a failed response: 503

Where: POST /api/v1/posts, POST /api/v1/posts/thread, POST /api/v1/posts/{id}/retry, POST /api/v1/ab-tests, POST /api/v1/posts/repurpose, POST /api/v1/accounts/{id}/recovery (verify_publishing)

Also returned with HTTP 200: POST /api/v1/posts/repurpose

What it means
Publishing capacity was briefly busy, so the post or item it names was not sent (unless the response also has reconciliationRequired or providerPublished). Other variants of an A/B test or other repurpose targets may already have published. The response usually has a Retry-After header, normally 30 seconds.
If this came from POST /api/v1/posts/repurpose
From repurpose: first make the fix this code's general guidance below describes (for example reconnect the same network account, change plan, or wait for any Retry-After). First follow the response code's remedy; ACCOUNT_REFRESH_RECONCILIATION_REQUIRED must be reconciled by support before any resend. Repurpose takes no Idempotency-Key, so the fix is judged against what this request already did: if an earlier attempt of the same request published or may have published some targets, send only the targets that are still missing, never the whole request. Read this response first to tell the two cases apart. As the whole response, a request-level refusal, so no target was processed in it, and this request can then be sent again, but only after confirming an earlier attempt of it published nothing; if it did or may have published some targets, send only the ones that are still missing. As one target's entry in data.results, other targets may already have published, so never resend the whole request; if that entry has providerPublished or reconciliationRequired the post may be live, so check it instead of retrying; otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again. If it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it and retry only that target in a new request naming just it, never both. If it is a draft, it cannot be retried, so delete it and then send only that target again; the deletion releases its reserved quota. In any other state, or if the deletion fails, contact support. Reading needs the posts:read scope and deleting posts:delete; without them, or if the deletion fails, contact support instead of retrying the target. With no postId and neither providerPublished nor reconciliationRequired, a draft may still have been saved if its acknowledgement was lost. Before retrying that target, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope), identify any draft created by this request and delete it with DELETE /api/v1/posts/{id} (posts:delete scope). Only after that deletion succeeds, or after confirming this request saved no draft, send only that missing target again. If you cannot identify the draft, lack the scopes or cannot complete its deletion, contact support instead of retrying. If the owner chose this target's content for the account recovery check post, that content is now live, so do not send that target again. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
From account recovery verification
Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. This replaces the general action below for responses from recovery verification. Repeat or recover a verification only through POST /api/v1/accounts/{id}/recovery. Never use POST /api/v1/posts/{id}/retry or a plain create for it, because only the recovery endpoint closes the account's incident. If the outcome is uncertain or in progress (reconciliationRequired, providerPublished, a recovery object, or an uncertain or in-progress code), never use a new key: repeat the recovery request with the original key or wait for reconciliation (for ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, only wait: do not repeat anything until the account is reconciled), because a new key publishes another real post. First fix the cause this entry describes (reconnect the same network account, complete the check the details name, restore permissions), then repeat or recover through the recovery endpoint. Only when the response settles that nothing was published (a failed post with none of those markers) is that verification over, and after ACCOUNT_REFRESH_RECONCILIATION_REQUIRED only once support has reconciled the account. If that response also carried data.id, read the post first: while it is in progress or its outcome is uncertain (IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_OUTCOME_UNCERTAIN, ACCOUNT_REFRESH_RECONCILIATION_REQUIRED, a recovery object, reconciliationRequired or providerPublished), keep the original key and wait or recover through the recovery endpoint only, and never retry or delete it. Once it is a settled failed post with no live markers, delete it (DELETE /api/v1/posts/{id}), or contact support instead: a recovery-verification post is never retried through POST /api/v1/posts/{id}/retry, because that endpoint does not close the account's incident. Only after that deletion succeeds, start a new verification: fix the cause and, with the owner's approval, start a new verification with a new Idempotency-Key. For INVALID_IDEMPOTENCY_KEY, nothing was bound, so correct the key's format and send the recovery request. For IDEMPOTENCY_CONFLICT, the key is already bound to an earlier request: keep that key and read GET /api/v1/posts/idempotency with it first; if the binding is that recovery verification, send the original recovery request unchanged to recover its outcome, and otherwise settle the bound post (or contact support) first, and use a new key only after that verification is confirmed not published and the owner approves. Otherwise apply the key guidance above to the recovery request.
What to do from any other endpoint
First: if the response also has reconciliationRequired or providerPublished, the post may be live: read it and do not retry. Otherwise: Wait for Retry-After, then follow the endpoint-specific action. For a keyed post or an A/B test, repeat the same request with the same Idempotency-Key; for an A/B test this resumes the same variants. For a thread, data.retryAction "create_thread" means send the same thread request again. From POST /api/v1/posts/{id}/retry, first read GET /api/v1/posts/{id} using the saved post ID. Retry that same post only if it is failed with no platformPostId, platformPostUrl or recovery object. If any such marker exists, the post is not failed, or it cannot be read, do not retry; wait for reconciliation or contact support. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
Inside an HTTP 200 response from POST /api/v1/posts/repurpose in post mode, as one target's code in data.results: the response itself succeeded, so the status listed above applies only when the same code is returned as a request-level refusal.

PUBLISH_OUTCOME_UNCERTAIN

HTTP status of a failed response: 409, 503

Where: POST /api/v1/posts/{id}/retry

What it means
The retry may have reached the network but its result is unknown, or an earlier attempt is still unresolved. data.reconciliationRequired is true, and data.providerPublished is true when the network accepted it. Only the retry endpoint sends this code: an uncertain first create is an HTTP 503 without a code (see Errors without a code), or 409 IDEMPOTENCY_OUTCOME_UNCERTAIN after a failed account refresh.
What to do
Do not retry again, and do not create a replacement or use a new key: the post may be live. Read the post with GET /api/v1/posts/{id}, using the ID from the request path (data.postId or data.id), check the network, and wait for reconciliation or contact support.

PROVIDER_RECONCILIATION_REQUIRED

HTTP status of a failed response: 503

Where: POST /api/v1/ab-tests

Also returned with HTTP 200: GET /api/v1/posts, GET /api/v1/posts/{id}, GET /api/v1/posts/idempotency, GET /api/v1/calendar, POST /api/v1/posts/auto-schedule

What it means
The result of a network call is unknown and needs reconciliation.
What to do
Do not create a replacement or publish again. From an A/B test, repeating the same request with the same Idempotency-Key is safe and does not duplicate posts. On a post's recovery.code, the post stays held until SocialCannon reconciles it; check the network or contact support if you need the outcome sooner. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.
Also appears in
HTTP 200 post objects (for example GET /api/v1/posts/{id} and GET /api/v1/posts/idempotency) as recovery.code, with recovery.kind "publish_outcome" or "provider_delete"; also as data.recovery.code on 409 and 410 idempotency replay responses.

Retrying a failed post

Answers from POST /api/v1/posts/{id}/retry that stop a retry.

THREAD_RETRY_UNSUPPORTED

HTTP status of a failed response: 409

Where: POST /api/v1/posts/{id}/retry

What it means
Failed threads cannot be retried through the single-post endpoint. With data.reconciliationRequired, the thread may have been partly published.
What to do
Without reconciliationRequired, create a new thread from the saved items. With it, do not create or replace a thread: the partial thread must be reconciled on the network first, so check what is live and contact support. Only create a new thread once reconciliation confirms that nothing from the earlier thread is live. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

PARTIAL_THREAD_COMPENSATION_REQUIRED

HTTP status of a failed response: 409

Where: POST /api/v1/posts/{id}/retry

What it means
This thread may include a live item that SocialCannon has not confirmed.
What to do
Do not retry or replace it. Contact support to reconcile the live chain.

LOCAL_PUBLISH_REPAIR_FAILED

HTTP status of a failed response: 503

Where: POST /api/v1/posts/{id}/retry

What it means
The network confirmed the post, but SocialCannon could not update its record.
What to do
Do not publish again. Calling retry later is safe: for a confirmed post it repairs the record without republishing.

Post state conflicts

The post changed, or is busy, while an update, retry or delete was being prepared.

PROVIDER_DELETE_IN_PROGRESS

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}, POST /api/v1/posts/{id}/retry, PATCH /api/v1/posts/{id}

Also returned with HTTP 200: GET /api/v1/posts, GET /api/v1/posts/{id}, GET /api/v1/posts/idempotency, GET /api/v1/calendar, POST /api/v1/posts/auto-schedule

What it means
Deleting this post on the network is pending.
What to do
From DELETE: repeat DELETE /api/v1/posts/{id} to finish the deletion; supported networks treat an already deleted post as done. If repeating it does not settle (for example PLATFORM_POST_ID_REQUIRED), read the post and contact support. From PATCH or retry: the post is being deleted, so do not update or republish it, and do not start a deletion you were not asked for; read the post again later. As a post's recovery.code, the deletion is still pending: do not republish, replace or change the post; read it again later.
Also appears in
HTTP 200 post objects as recovery.code, with recovery.kind "provider_delete"; also as data.recovery.code on 409 and 410 idempotency replay responses.

USAGE_RESERVATION_OWNER_UNCERTAIN

HTTP status of a failed response: 409

Where: POST /api/v1/posts/{id}/retry, PATCH /api/v1/posts/{id}, DELETE /api/v1/posts/{id}, POST /api/v1/ab-tests

What it means
SocialCannon cannot match the usage held for this post to its owner.
What to do
Do not retry. Contact support.

POST_DELETED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The post was deleted. With data.reconciliationRequired, the network post has not been proven removed.
What to do
Without reconciliationRequired, nothing more is needed for this post; create a new one if you still want it. With reconciliationRequired, read the post and check the network first, and do not create a replacement until the original is confirmed gone; contact support if it is still live. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

PUBLISH_IN_PROGRESS

HTTP status of a failed response: 409

Where: PATCH /api/v1/posts/{id}, DELETE /api/v1/posts/{id}

What it means
The post is publishing, or waiting for its outcome to be reconciled, so it cannot be changed now.
What to do
Read the post again later with GET /api/v1/posts/{id}. Once publishing has settled, send a deletion again if you still want it; send an update again only if the post is back in an editable state (draft, scheduled or awaiting_account). Do not publish a replacement post while this post is publishing, because it may still go out.

PUBLISH_ATTEMPT_MISMATCH

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The post changed while the request was being prepared.
What to do
Read the post again and decide from its current state. Do not publish it again.

PROVIDER_ID_MISMATCH

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The post's recorded network identity does not allow this change, for example because it is already published.
What to do
Do not publish it again. Read the post, and contact support if its state looks wrong.

PROVIDER_DELETE_NOT_JOURNALED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The record of a pending network deletion changed or is incomplete.
What to do
Read the post again. If it still shows a pending deletion, contact support.

PARTIAL_THREAD_RECONCILIATION_REQUIRED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The recorded X post IDs for this thread may cover only part of the live chain.
What to do
Contact support to reconcile the whole chain before deleting it.

Deleting a post

Answers from DELETE /api/v1/posts/{id}.

ACCOUNT_AUTHORITY_CHANGED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The connected account changed while the deletion was being prepared, so this request deleted nothing.
What to do
If an earlier deletion of this post was interrupted, read the post first with GET /api/v1/posts/{id}: anything that deletion already removed stays removed. Retry the deletion. If the account was reconnected to a different network account, reconnect the original one first; the post can only be deleted through the account that published it.

ACCOUNT_UNAVAILABLE

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The post's account is missing, disconnected or no longer matches the post's platform.
What to do
Reconnect the original network account, then retry the deletion. If that account no longer exists, contact support.

CREDENTIAL_REFRESH_FAILED

HTTP status of a failed response: 503

Where: DELETE /api/v1/posts/{id}

What it means
SocialCannon could not renew the account's access. No network deletion was attempted.
What to do
Retry the deletion later.

CREDENTIAL_REFRESH_RECONCILIATION_REQUIRED

HTTP status of a failed response: 503

Where: DELETE /api/v1/posts/{id}

What it means
SocialCannon could not safely renew the account's access. No network deletion was attempted.
What to do
Do not retry yet, and do not reconnect first: an earlier operation on the account is unresolved. Contact support, and retry the deletion once it is reconciled.

PLATFORM_POST_ID_MISMATCH

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The platformPostId in the request body does not match the one recorded for this post.
What to do
Read the post and send its recorded ID as { "strictCompensation": true, "platformPostId": "<recorded id>" }, or send no body.

PLATFORM_POST_ID_UNVERIFIED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
A platformPostId was sent, but none is recorded for this post. SocialCannon never deletes an ID it did not record.
What to do
Read the post. If it is a draft, scheduled or failed post with no platformPostId, platformPostUrl, publishedAt or recovery object, send DELETE /api/v1/posts/{id} again without a body to remove it; a scheduled post left in place will still publish. Contact support if it is published or shows any provider evidence, or if it is live on the network.

PLATFORM_POST_ID_REQUIRED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
The post may have reached the network, but no exact network post ID is recorded, so it cannot be deleted safely.
What to do
Check the network. If the post is live there, remove it on the network yourself. Either way, contact support so the SocialCannon record can be settled: without the network post ID, the API cannot delete it.

LEGACY_PROVIDER_DELETE_UNVERIFIED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
An older deleted post has no proof that it was removed from the network.
What to do
Contact support.

PLATFORM_DELETE_UNSUPPORTED

HTTP status of a failed response: 409

Where: DELETE /api/v1/posts/{id}

What it means
This network does not let SocialCannon delete published posts through its API (Instagram and TikTok). The SocialCannon post is kept.
What to do
Delete the post in the network's own app, then contact support so the SocialCannon record (which keeps data.reconciliationRequired) can be settled. Do not publish it again.

PLATFORM_DELETE_FAILED

HTTP status of a failed response: 503

Where: DELETE /api/v1/posts/{id}

What it means
The network rejected or failed the deletion. With data.reconciliationRequired, part of it may have happened.
What to do
Without reconciliationRequired, retry the deletion. With it, check the network before retrying.

LOCAL_DELETE_FAILED

HTTP status of a failed response: 503

Where: DELETE /api/v1/posts/{id}

What it means
SocialCannon could not finish deleting its own record.
What to do
Retry the request.

LOCAL_DELETE_JOURNAL_FAILED

HTTP status of a failed response: 503

Where: DELETE /api/v1/posts/{id}

What it means
SocialCannon could not safely start the network deletion. No network deletion was attempted.
What to do
Retry the deletion later.

LOCAL_DELETE_PERSISTENCE_FAILED

HTTP status of a failed response: 503

Where: DELETE /api/v1/posts/{id}

What it means
SocialCannon could not save the deletion of its own record. With data.providerDeletionConfirmed, the network post is already gone; data.reconciliationRequired is also set until the record is saved.
What to do
Repeat the deletion: it resumes the same deletion, and networks that support deletion treat an already deleted post as done.

A/B tests, auto-schedule and repurpose

Codes specific to operations that create several posts at once.

INSUFFICIENT_ELIGIBLE_VARIANTS

HTTP status of a failed response: 503

Where: POST /api/v1/ab-tests

What it means
The A/B test ended with fewer than two eligible published variants. Its active-test slot was released. Some variants may already be live: data.variants shows each one's state and platformPostId.
What to do
A replacement test needs a new Idempotency-Key and publishes new posts. Before reusing a variant's content, delete with DELETE /api/v1/posts/{id} every variant post in data.variants that is not already deleted (provisioned, scheduled, awaiting_account, publishing, published, reconciliation_required or failed); leaving it out is not enough, because a scheduled one still publishes and a failed one can still be retried. If any of those deletions cannot be completed (for example PLATFORM_DELETE_UNSUPPORTED, PUBLISH_IN_PROGRESS or a reconciliation code), do not create the replacement test; contact support. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

PARTIAL_FAILURE

HTTP status of a failed response: 503

Where: POST /api/v1/ab-tests

What it means
The A/B test is active, but some variants failed definitively and are excluded from the comparison.
What to do
Read data.variants. The test continues with the rest; no retry is needed.

PROVIDER_AUTHORITY_CHANGED

HTTP status of a failed response: 409

Where: POST /api/v1/ab-tests

What it means
The social account changed after the A/B test was set up. Its posts can still be recovered with the same Idempotency-Key.
What to do
Reconnect the exact account, then repeat the request with the same key. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

AB_TEST_OPERATION_INCOMPLETE

HTTP status of a failed response: 503

Where: POST /api/v1/ab-tests

What it means
The A/B test is set up, but processing stopped part way.
What to do
Repeat the request with the same Idempotency-Key to resume the same posts. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

AUTO_SCHEDULE_RETRY_REQUIRED

HTTP status of a failed response: 500

Where: POST /api/v1/posts/auto-schedule

What it means
The auto-schedule operation is incomplete. data.scheduled, data.pending and data.unscheduled list each item's state.
What to do
Repeat the request with the same Idempotency-Key to resume the pending items. Items in data.unscheduled are settled and will not be retried by a replay: read their reason and schedule only those items separately if still wanted. Never resend the original payload under a new key, because items in data.scheduled would be scheduled twice. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

AUTO_SCHEDULE_ACCOUNT_AUTHORITY_CHANGED

HTTP status of a failed response: 409

Where: POST /api/v1/posts/auto-schedule

What it means
The account behind an existing auto-schedule operation is gone, inactive or different.
What to do
Reconnect the exact account, then repeat the original request with the same Idempotency-Key to resume the operation; if that account cannot be reconnected, contact support to reconcile the listed items. Do not resend under a new key. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

AUTO_SCHEDULE_RECONCILIATION_REQUIRED

HTTP status of a failed response: 500

Where: POST /api/v1/posts/auto-schedule

What it means
The operation's record points at a post that is missing.
What to do
Contact support. Do not resend under a new key.

REPURPOSE_UNAVAILABLE

HTTP status of a failed response: 503

Where: POST /api/v1/posts/repurpose

What it means
The AI adaptation failed. Nothing was drafted or posted. details.retryable says whether retrying can help, and details.missingPlatforms names a platform the model left out.
What to do
If retryable is true, retry later, optionally without the missing platforms. If false, retrying will not help until SocialCannon fixes its AI provider. This request published nothing. If it was itself a retry of an earlier repurpose request that may have published some targets, never resend the whole request: send only the targets that are still missing. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

REPURPOSE_CONTENT_REJECTED

HTTP status of a failed response: 422

Where: POST /api/v1/posts/repurpose

What it means
The AI provider declined to adapt this text, for example because of a content filter.
What to do
Edit the source text before trying again. This request published nothing. If it was itself a retry of an earlier repurpose request that may have published some targets, never resend the whole request: send only the targets that are still missing. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

NO_PUBLISHABLE_TARGETS

HTTP status of a failed response: 400

Where: POST /api/v1/posts/repurpose

What it means
In post mode, no target account can publish, so nothing was generated. data.results explains each platform.
What to do
Fix the accounts named in data.results, then send the request again. This request published nothing. If it was itself a retry of an earlier repurpose request that may have published some targets, never resend the whole request: send only the targets that are still missing. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

Errors without a code

These failures have no code field. Handle them by HTTP status and the fields shown.

HTTP 400

When
"Invalid input" (details holds the field errors), "Content validation failed" (details lists the platform rules broken), "Social account is not active", a missing Idempotency-Key or invalid body on POST /api/v1/accounts/{id}/recovery, an Idempotency-Key that is not paired with client_secret or is not a canonical lowercase UUIDv4 on POST /api/v1/auth/clients, or a GET /api/v1/calendar range longer than the plan allows ("Calendar range limited to N days on your plan"). Also a retry on a non-failed post ("Cannot retry post with status …") or a PATCH on a non-editable post ("Cannot update post with status …"). Also DELETE /api/v1/ab-tests/{id} or POST /api/v1/ab-tests/{id}/complete on a test whose status does not allow it ("Cannot cancel test with status …", "Cannot complete test with status …").
What to do
For "Social account is not active", reconnect the same network account before trying again, then apply the saved-post rules below if data.id is present; keep any original key when resending an unchanged fresh create. For "Cannot retry post with status" or "Cannot update post with status", do not resend unchanged: read GET /api/v1/posts/{id} and act on its current status. Only failed posts can use the retry endpoint, and a live provider identity or recovery object must be resolved before any new publication; PATCH edits only a draft, scheduled or eligible awaiting_account post. For an A/B test cancel or complete refused because of its status, nothing changed: do not send it again; read the test with GET /api/v1/ab-tests/{id} and act on its current status. For POST /api/v1/auth/clients, send the Idempotency-Key together with the same client_secret, as a canonical lowercase UUIDv4. For repurpose post mode, follow the full repurpose recovery rule above before sending a corrected target; a validation failure does not prove an earlier attempt published nothing. For A/B tests or auto-schedule, retain the original Idempotency-Key when resending; if a corrected body conflicts with an existing binding, read and reconcile that operation instead of starting under a new key. For a thread, check any previously saved post and every live item before a replacement; if its outcome is unclear, contact support instead of sending another thread. Otherwise, fix the request and send it again. If a keyed POST /api/v1/posts response carries data.id, the key is settled and repeating it will not publish: if the cause was the account (restored now), retry that post with POST /api/v1/posts/{id}/retry; if it was the content or the account ID, which the retry endpoint cannot change, create a new post with a new key after confirming it has no recovery object, platformPostId or platformPostUrl. Do one or the other, never both: delete the failed post before replacing it. For account recovery verification, use neither: start a new verification through POST /api/v1/accounts/{id}/recovery with the owner's approval. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 401

When
"Missing or invalid Authorization header" or "Invalid or expired token": the bearer token is missing, malformed or past its one-hour life. "Client is deactivated": the API client itself was switched off.
What to do
For a token problem, get a new token from POST /api/v1/auth/token. A deactivated client cannot get a working token; contact support. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 403

When
"Insufficient scopes" names the missing scope. POST /api/v1/ab-tests also returns 403 without a code when A/B testing is not on the plan or the test has more variants than the plan allows.
What to do
Use a client with the scope, or upgrade the plan. For an A/B test with more variants than the plan allows, you can instead send fewer variants. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 404

When
The requested resource (a post, account, engagement, A/B test or API client) does not exist or belongs to another client. Engagement reads and replies also return "Associated account not found or inactive".
What to do
For "Associated account not found or inactive", restore or reconnect the same network account, then confirm the associated account is active before repeating the request; if the saved post or engagement still refers to a missing account, contact support. Before repeating a reply, check the comment thread first and do not blindly resend it. Otherwise, check the ID. Lists are available from the matching GET endpoint. If a keyed POST /api/v1/posts response carries data.id, the key is settled and repeating it will not publish: if the cause was the account (restored now), retry that post with POST /api/v1/posts/{id}/retry; if it was the content or the account ID, which the retry endpoint cannot change, create a new post with a new key after confirming it has no recovery object, platformPostId or platformPostUrl. Do one or the other, never both: delete the failed post before replacing it. For account recovery verification, use neither: start a new verification through POST /api/v1/accounts/{id}/recovery with the owner's approval. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 200

When
POST /api/v1/posts/repurpose in post mode: an entry in data.results with success false and only an error message, no code (for example media that could not be fetched, a missing TikTok privacy level, or a usage limit reached while publishing).
What to do
If the entry has providerPublished or reconciliationRequired, the post may be live: check it and do not retry. Otherwise, if the entry has a postId, a post was saved: read it first. If it is published or has a platformPostId, platformPostUrl or recovery object, keep it and do not send that target again; only if it is failed with no live markers, either retry it with POST /api/v1/posts/{postId}/retry or delete it before retrying the target in a new request, never both; in any other state, contact support and do not retry the target. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again. With neither, a draft may still have been saved if the failure came while saving it, and it can count against your post quota. Before retrying, list that account's drafts with GET /api/v1/posts?status=draft&platform={platform}&accountId={accountId} (posts:read scope) and delete any created during this request with DELETE /api/v1/posts/{id} (posts:delete scope), which releases it from your quota; if you lack those scopes, the deletion fails, or you cannot tell whether a draft came from this request, contact support instead of retrying. Then fix what the message names and retry only that target in a new request. Never resend the whole request, because other targets may have published.

HTTP 200

When
POST /api/v1/analytics/refresh: a result with success false and no code (for example an inactive account or an unsupported platform). A skipped Instagram Story carries INSTAGRAM_STORY_EXPIRED instead.
What to do
Nothing changed for that post. Fix the cause named in the result, or leave it; refreshing again is safe.

HTTP 409

When
POST /api/v1/posts or POST /api/v1/posts/thread with scheduledAt "optimal": "No optimal time slot available in the next 7 days."
What to do
Nothing was created. Send the post or thread with an explicit scheduledAt instead. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 409

When
DELETE /api/v1/ab-tests/{id}: "The A/B test changed before it could be canceled". POST /api/v1/ab-tests/{id}/complete: the test cannot complete yet (fewer than two eligible variants are published, a variant is unresolved, or analytics are not yet available for every eligible variant), or a variant changed before completion.
What to do
Nothing changed. Read the test with GET /api/v1/ab-tests/{id}. Cancel again only if it is still active or provisioning; complete it later, once its variants are published and their analytics are available. Do not create a replacement test because of this response.

HTTP 429

When
The per-client rate limit was exceeded.
What to do
Wait for the Retry-After header, then continue. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 503

When
POST /api/v1/posts (or account recovery verification) answered with data.id and no code: the publish outcome is uncertain, or a failure could not be recorded. data.reconciliationRequired is usually set; data.providerPublished: true means the network accepted the post but SocialCannon could not record it.
What to do
Do not resend it as a new post or under a new key, and do not create a replacement. If you sent an Idempotency-Key, repeating the identical request with that key is safe; without one, never repeat the request, because it would create a second post. Read GET /api/v1/posts/{id} with data.id first; if you sent an Idempotency-Key, GET /api/v1/posts/idempotency is an extra check, but a 404 there does not prove nothing exists, because the key may not have been bound. For recovery verification, repeat only POST /api/v1/accounts/{id}/recovery with the original key, never POST /api/v1/posts/{id}/retry or a plain create. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 503

When
POST /api/v1/posts/thread answered with data.id and no code: the thread's outcome is uncertain. data.providerPostIds and data.providerPublished: true mean some items are live; data.reconciliationRequired is set while it is unresolved.
What to do
Do not create another thread. Read the post with GET /api/v1/posts/{id} and check the live items on the network; contact support to reconcile it.

HTTP 503

When
POST /api/v1/posts/{id}/retry answered with no code: the retry's outcome is uncertain, or its failure could not be recorded.
What to do
Do not call retry again yet and do not create a replacement. Read GET /api/v1/posts/{id}; contact support if it does not settle.

HTTP 503

When
POST /api/v1/engagements/{id}/reply: "Failed to reply", with no code. The network may or may not have posted the reply.
What to do
Do not resend automatically. Check the comment thread on the network first, then reply again only if your reply is missing.

HTTP 503

When
POST /api/v1/media/upload-complete: "Upload could not be finalized."
What to do
Call upload-complete again with the same publicUrl; finalizing the same upload twice is safe.

HTTP 503

When
A read such as GET /api/v1/posts/{id}/analytics or GET /api/v1/posts/{id}/engagements failed upstream ("Failed to fetch ...").
What to do
Retry later; these requests change nothing on the network.

HTTP 503

When
POST /api/v1/ab-tests: "The A/B test could not be provisioned."
What to do
Repeat the request with the same Idempotency-Key. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

HTTP 501

When
POST /api/v1/posts/repurpose when AI repurposing is not configured on this server. No work was started.
What to do
Do not retry in a loop. Contact support.

HTTP 500

When
An unexpected server error.
What to do
For a write, treat the outcome as unknown and do not resend it automatically. A keyed request (posts, A/B tests, auto-schedule, account recovery verification through its recovery endpoint, and API client provisioning with the same key and client_secret) can be repeated with its original key, or looked up first with GET /api/v1/posts/idempotency for posts. An unkeyed post, thread or repurpose request may already have been saved (an unkeyed client provisioning may have created a client that the API cannot list, so contact support before provisioning again): do not send it again until both are settled, in this order. First, the network shows it was not published (checking GET /api/v1/posts alone is not enough, because the network may have accepted it before SocialCannon recorded it). For a repurpose request, check every target you asked for, not only one, and never resend the whole request once any target may have published: send only the target that is still missing. Then, SocialCannon has no saved copy: look for it in GET /api/v1/posts, including status=scheduled and draft, and delete a saved copy you are replacing, because a saved scheduled copy can still publish later. If the network shows it live or you cannot tell, keep any saved copy and contact support; also contact support if you cannot identify and settle the original. Before you publish this content again, check whether the owner already published it as the account recovery check post: if that content is now live, do not publish it again.

The full request and response formats are in the API reference. Stuck on an error? Email support@socialcannon.app with the code, the post ID and the time of the request.