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:
Your application to the publishing API: Your n8n workflow, queue worker or backend sends
POST /uploads/startorPOST /videos/import. If a reverse proxy returns502 Bad Gatewayor the client times out after the server already committed the transaction, a naive client retry submits a brand-new publish request.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
ECONNRESETorETIMEDOUToccurs while waiting for the response to Instagram'smedia_publishor Facebook'sreel_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 |
|---|---|---|---|
|
| Unique index on | HTTP 202 with the existing |
| Per-item | Unique index on | Returns the existing import row with |
Per-destination task creation | Resolved | Unique constraint on | 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 |
| The social network never received a request. |
|
Pre-commit metadata & session init |
| Opening an upload session or creating an unfinalized container does not publish a post without a subsequent transfer and publish call. |
|
Pre-commit byte transfer |
| Incomplete bytes cannot become a live post without the explicit finish/publish step. |
|
Explicit rate-limit rejection before acceptance |
| The platform explicitly rejected the call before accepting a multi-step operation. |
|
Single-call URL publish or final commit |
| A single call or final commit triggers publication. If the response is lost in transit, the post may already exist. |
|
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),retryPublishTasksskips any task whereunknownOutcomeis true and returns it in theskipped[]array withcode: "unknown_outcome"andneedsConfirmation: true. You must first check the destination account, and only passconfirmUnknownOutcome: trueonce 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,
retryPublishTasksalso 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.
RFC 9110 §9.2.2: Idempotent Methods — IETF HTTP Semantics, checked October 25, 2026
Content Posting API: Direct Post — TikTok for Developers, checked October 25, 2026




