A publishing request can succeed even when your application never receives the response. If a worker treats that timeout as a failure and immediately repeats the request, the same announcement may appear twice. A reliable social publishing integration starts by representing uncertainty explicitly.
Model delivery per account
Create a separate job for every destination account. Store the article version, provider, account, scheduled time and media references with the job. One provider succeeding must not cause another provider's job to be marked successful, and retrying one destination must never resend the already confirmed ones.
A useful internal state model is: draft, queued, sending, media processing, published, and needs review. These names describe your application, not a universal provider API. Save a remote identifier and permalink when available. A container identifier can mean only that an upload is being processed; it does not necessarily prove a public post exists.
If an image is required, track its confirmation independently where the provider exposes that information. A successful text post without the required attachment is not complete delivery.
Authenticate before queueing work
Verify that the token belongs to the destination account and has the permissions required for the operation. A login to a personal profile does not automatically grant publication rights to a page or organization. Provider rules and endpoint availability can change, so consult the provider's current documentation before implementation.
Keep tokens on the server in a secret store, restrict access, and keep credentials out of logs. Provide a way to revoke access and reconnect when a token expires. Use least privilege and make an authorization failure visible to an operator instead of repeatedly sending the same request.
Separate transient errors from unknown outcomes
A malformed payload or rejected permission normally requires correction. A rate limit may require waiting according to the provider's guidance and a Retry-After header where supplied. For safe status checks, use bounded exponential backoff with jitter. Avoid an unlimited retry loop.
A server error or timeout after sending a create request is different: the service might have created the post before the connection failed. Record the attempt and move the job to needs review. Query the existing operation or post if the provider offers a reliable lookup. If not, use an operator review; an empty search result is not always conclusive evidence that no post exists.
Idempotency is a contract
When the provider documents an idempotency key for the creation endpoint, reuse a stable key for the same logical job and follow its retention and payload rules. Adding an arbitrary header to an endpoint that does not support it does not create idempotency.
Within your own system, enforce one job per publication version and destination account. Atomically claim queued jobs so concurrent workers cannot both start the same operation. Save an attempt before sending and save the remote identifier as soon as a response arrives.
These local measures reduce concurrency bugs, but they cannot close the gap between a remote success and a lost response. Provider-supported idempotency or reconciliation is still necessary.
Media is a separate lifecycle
Some services use a two-step process: create an upload or media container, wait for processing, and then publish. Save the container ID and poll that same object at a reasonable interval. Do not create a fresh container every time processing takes longer than expected.
Validate the provider's current requirements for media format, dimensions, size and accessibility. A URL that opens in your browser may still be inaccessible to a provider's fetcher. Expiring links and redirects deserve explicit tests. Never present a media attachment as confirmed merely because the upload request was accepted.
Keep a useful operational record
For each job, retain the article ID, content version, destination, state, attempt timestamps, next check time, safe error code and remote ID. Do not log access tokens or unnecessary personal data. Alert on stale processing jobs, repeated authorization failures and accumulating uncertain results.
If you consume webhooks, verify their signatures according to the provider's documentation and handle duplicate delivery safely. Use events to inform state, not to assume that every event arrives once and in order.
A recovery walkthrough
- Two destinations receive the same announcement as separate jobs.
- The first confirms a remote post ID and permalink. Mark only that job published.
- The second returns a media container that is still processing. Store its ID and check the same container.
- Once ready, send the publish request. The connection drops before the response arrives.
- Mark the second job as needing review. Reconcile using the provider's supported lookup or an operator's inspection. Create a new attempt only when there is reliable evidence the original did not publish.
The first destination remains untouched throughout this recovery.
Launch checklist
- Confirm account permissions and a safe token rotation process.
- Validate payloads and media against each provider's current documentation.
- Protect the queue against concurrent claims.
- Document which operations are safe to retry and whether idempotency is supported.
- Route ambiguous create outcomes to reconciliation, not automatic reposting.
- Save remote identifiers and permalinks, and monitor jobs stuck in processing.
- Test revoked tokens, inaccessible media, rate limits, delayed processing and lost responses.
Start with a controlled test account. Compare the public result with your job history, then expand to more destinations after the team can reliably tell a confirmed post from an uncertain attempt.
Further reading: HTTP Semantics, RFC 9110.
Russian companion article: https://morlix.ru/blog/publikatsiya-v-sotsseti-cherez-api-statusy-oshibki-povtory
Top comments (0)