Skip to main content
Network calls fail in ways that leave you unsure whether the request went through. Idempotency keys make retries safe: replay the same request with the same key and MADIAD Hub returns the original result instead of publishing again.

Send an idempotency key

Add an Idempotency-Key header with a value you control — a UUID per logical action is ideal. The Hub also accepts X-Idempotency-Key or X-Request-Id as equivalents.

How it behaves

  • First request with a key — processed normally; the result is stored against that key.
  • Replay with the same key and the same content — returns the stored result; no second post is created, and the response carries Idempotent-Replayed: true.
  • Same key, different content — rejected with 409 idempotency_conflict. Nothing is published.
  • Different key — treated as a brand-new request.
  • A post every platform refused (status: "failed") — nothing was published, so its key is released. Fix the content and send it again with the same key or a new one.
Generate the key before the first attempt and reuse it for every retry of that same action. Generating a new key on retry defeats the purpose.

Telling a replay apart from a fresh publish

A replayed response is identical to the original — same request_id, same status. That is the point, but it means an automation whose key stops changing keeps receiving successful-looking responses while nothing new is being published. Every replayed response therefore carries a header:
A fresh publish never sets it. If you run scheduled or queued publishing, treat this header as an alarm: it means the key you sent had already been used, so the content you just submitted did not go out.
Use a new key for every new post. A counter that stops advancing, a retried workflow item, or a template that hardcodes the key will all send content under a key that is already spoken for. Since 26 July 2026 that returns 409 idempotency_conflict when the content differs — before then it silently returned the earlier result.

When the outcome is unknown

A publish can take longer than MADIAD Hub is allowed to wait. When that happens the request is not reported as a failure, because the post may well have gone out — we stopped waiting, the platform did not stop working. You get 502 with code upstream_timeout, nothing is refunded, and the key you sent is closed against that answer. Replaying it returns the same 502 and the same body — deliberately, so an automation branching on the status code cannot record an unknown post as a success.
The request_id in that answer is the handle on the post. MADIAD Hub keeps following it, and you can too. What to do:
  1. Poll GET /v1/posts/status with that request_id. It answers unknown until the platforms’ side has picked the post up, then processing, then the outcome (completed, draft, partial or failed). The post history settles by itself as well: when the platforms report back, and at the latest at the next daily check.
  2. Do not send it again while it reads unknown or processing — the first one may be live or on its way.
  3. If it ends failed, nothing was published: the upload is given back and the same Idempotency-Key is open again.
  4. A text or video post sent to publish now that never reached the platforms is ruled failed by the daily check, not before. A photo or document post, and any post sent for later, stays unknown in that case: check history or the platform itself, and if it did not publish, send it again with a new Idempotency-Key.
  5. Never retry it automatically on the same key expecting a different result: the old key keeps answering this same 502, even after the post has settled. The status poll and the history are where the outcome is.
A post sent for later (scheduled_at or add_to_queue) that ends this way has job_id: null: there is no schedule handle yet. Once MADIAD Hub has read it back (when the platforms’ side reports, at the latest at the daily check), the post history carries the job_id that cancels or moves it. One exception: a post with a per-platform caption goes out as two jobs. If one was accepted and the other’s answer was lost, the answer carries the accepted job’s job_id, and cancelling with it cancels that part only; the other part is read back after the post’s time.

When to use it

Always, for any request that creates something — posts in particular. It’s essential when:
  • A client or workflow tool (n8n, queues, cron) auto-retries on timeout.
  • A webhook or job may be delivered more than once.
  • A user double-clicks publish.
Keys are scoped to your account and remembered long enough to cover realistic retry windows.