Uplonic Logo

How to Avoid Duplicate Posts in a Social Media API in 2026

A lost HTTP response after media transfer does not mean a post failed. Learn why naive HTTP retries create duplicate social posts, and how Uplonic uses client idempotency keys, per-credential task constraints, pre-commit retry classification and unknownOutcome gates to stop duplicates.

How to Avoid Duplicate Posts in a Social Media API in 2026AI
On this page

To avoid duplicate posts when integrating with a social media API, you must separate two different failure boundaries: client-to-API submission retries (solved with an Idempotency-Key and unique database constraints) and worker-to-platform publishing retries (solved by only auto-retrying pre-commit operations where no post could have been created). If a connection drops during the final commit call to Instagram, TikTok, Facebook or LinkedIn, the outcome is unknown—and retrying automatically risks publishing the same video twice.

For a hands-on walkthrough of submitting and deduplicating a video request with cURL, start with our guide to publishing video through a social media API. This article explains the underlying queue, database and retry architecture that keeps retries from turning into double posts.

Why naive HTTP retries publish the same video twice

As RFC 9110 Section 9.2.2 defines, POST is not an idempotent HTTP method: repeating an identical POST request after a connection reset or gateway timeout is not guaranteed to have the same effect as a single request. In social media publishing, a single logical post often crosses two network hops:

  1. Your application to the publishing API: Your n8n workflow, queue worker or backend sends POST /uploads/start or POST /videos/import. If a reverse proxy returns 502 Bad Gateway or the client times out after the server already committed the transaction, a naive client retry submits a brand-new publish request.

  2. The publishing worker to the social platform: Uplonic's worker uploads video bytes and sends the final publish call to TikTok, Instagram, Facebook, YouTube or LinkedIn. If an ECONNRESET or ETIMEDOUT occurs while waiting for the response to Instagram's media_publish or Facebook's reel_finish, the platform may already be publishing the post.

Asking "is this error transient?" is necessary, but it is the wrong sufficient condition for an automatic retry. As documented in Uplonic's retry policy, the real question is: can we prove that no content was created on the platform?

Layer 1: Client-level idempotency for imports and publish requests

Stopping duplicates at the first hop requires the server to recognize a repeated logical operation and return the original record, even when two identical requests arrive concurrently. Uplonic implements this across both media ingestion and publishing:

Endpoint / Service

Idempotency input

Database constraint & race handling

Response on duplicate

POST /uploads/start

Idempotency-Key or X-Idempotency-Key HTTP header (trimmed, 1–255 characters).

Unique index on (appId, idempotencyKey) on PublishRequest. Pre-read fast path plus Prisma P2002 unique-violation catch for concurrent races.

HTTP 202 with the existing publishRequestId, idempotent: true, and no second worker wake-up.

POST /videos/import & MCP import_videos

Per-item idempotencyKey field (8–200 characters), prefixed internally with the caller scope (api:... or mcp:<grantId>:...).

Unique index on (appId, idempotencyKey) on VideoImport. Rejects duplicate keys in the same batch and catches P2002 on parallel calls.

Returns the existing import row with deduplicated: true without re-downloading the source URL.

Per-destination task creation

Resolved PlatformCredential.id per target channel.

Unique constraint on (publishRequestId, platformCredentialId) on PublishTask, plus SELECT ... FOR UPDATE locking when editing scheduled platforms.

Guarantees at most one task per connected account within a publish request.

When you send a request with an Idempotency-Key, createPublishRequest commits the PublishRequest and all per-channel PublishTask rows inside a single database transaction before returning HTTP 202. If two parallel retries hit the endpoint at the same millisecond, the database unique index rejects the second insert with P2002, and the catch block immediately looks up and returns the winning request with deduplicated: true.

Layer 2: Pre-commit vs. commit operations in the platform worker

Once a PublishTask is claimed by the worker, an idempotency key sent to Uplonic cannot force every upstream social network to be idempotent—most social APIs do not accept client idempotency keys on post creation. Instead, decideRetry inspects which step of the platform upload failed.

Operation phase

Checked operation names

Why it is safe (or unsafe) to auto-retry

Worker decision on transient error

Before any platform call

beforePlatformCall: true (S3 download, ffprobe, local context preparation)

The social network never received a request.

decision: "retry" (automatic backoff)

Pre-commit metadata & session init

creator_info, upload_init, video_init, image_init, media_init, container_create, reel_init

Opening an upload session or creating an unfinalized container does not publish a post without a subsequent transfer and publish call.

decision: "retry"

Pre-commit byte transfer

chunk_upload*, video_chunk_upload, media_add, upload_transfer, reel_transfer

Incomplete bytes cannot become a live post without the explicit finish/publish step.

decision: "retry"

Explicit rate-limit rejection before acceptance

errorClass === "rate_limit" (HTTP 429) when platformAccepted === false

The platform explicitly rejected the call before accepting a multi-step operation.

decision: "retry"

Single-call URL publish or final commit

pull_url_init (TikTok URL pull), upload_via_url (Facebook), reel_finish, video_post_create, Instagram/Threads media_publish

A single call or final commit triggers publication. If the response is lost in transit, the post may already exist.

decision: "fail" with unknownOutcome: true

Notice why pull_url_init (TikTok's PULL_FROM_URL mode, explained in our TikTok Content Posting API guide) and Facebook's upload_via_url are deliberately excluded from PRE_COMMIT_OPERATION_PREFIXES. Unlike chunked file uploads—which require a separate completion step—a URL-pull initialization instructs the platform to fetch and publish the video in one step. If the network connection drops before the response arrives, repeating that call would start a second publication.

Similarly, for Instagram and Threads container publishing, Uplonic's status poller checks the container's status before calling media_publish. It only publishes when the container status is FINISHED, extends its claim window with a conditional leaseOwner update (extendPollClaim) before mutating, and treats a container that already transitioned to PUBLISHED as completed without calling media_publish a second time.

Layer 3: Handling unknownOutcome and per-task manual retries

When a task fails at a commit boundary with an uncertain outcome, Uplonic sets unknownOutcome = true on the PublishTask and stops automatic retries. When you or your application later call POST /uploads/requests/:id/retry (implemented in retryPublishTasks), the API enforces three rules:

  • Per-task isolation: If a request targeted YouTube, TikTok and Instagram, and only Instagram failed, retrying the request only re-queues the failed PublishTask. Completed sibling tasks remain untouched.

  • Explicit confirmation gate for unknown outcomes: By default (confirmUnknownOutcome: false), retryPublishTasks skips any task where unknownOutcome is true and returns it in the skipped[] array with code: "unknown_outcome" and needsConfirmation: true. You must first check the destination account, and only pass confirmUnknownOutcome: true once you have verified the post is not live. See our step-by-step guide to diagnosing and retrying failed posts for the exact request and response payloads.

  • Pre-flight health checks: Before re-queuing, retryPublishTasks also verifies that the channel credential is still active (platform_disconnected) and that the source video has not been purged by storage retention (media_deleted).

To observe final task outcomes without aggressive polling loops, pair your idempotent submission flow with signed event notifications as described in our guide to social media publishing webhooks.

Sources & methodology

Method: primary-source review of RFC 9110 and TikTok Direct Post documentation alongside direct source inspection of Uplonic's publishing queue, retry policy, status poller, uploads router and video import service on October 25, 2026.

ShareXLinkedInFacebook

Get the next guide by email

Creator guides, earnings data and the platform changes that affect your reach. Two emails a month at most, unsubscribe anytime.

Your videos everywhere automatically.

Connect your channels, plan with an AI copilot, automate via Claude or Codex, and track publishing from one unified dashboard.

Start for free

TikTok
TikTok scheduled6:00 PM · TikTok
Instagram
Instagram uploaded3 uploads today
Facebook
Schedule activeNext upload: 6:00 PM · TikTok
Hand holding a smartphone with the Uplonic dashboard
Uplonic app on mobile phone showing video scheduling interface