Send an idempotency key
Add anIdempotency-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.
Telling a replay apart from a fresh publish
A replayed response is identical to the original — samerequest_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:
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 get502 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.
request_id in that answer is the handle on the post. MADIAD Hub keeps following it, and you can too.
What to do:
- Poll
GET /v1/posts/statuswith thatrequest_id. It answersunknownuntil the platforms’ side has picked the post up, thenprocessing, then the outcome (completed,draft,partialorfailed). The post history settles by itself as well: when the platforms report back, and at the latest at the next daily check. - Do not send it again while it reads
unknownorprocessing— the first one may be live or on its way. - If it ends
failed, nothing was published: the upload is given back and the sameIdempotency-Keyis open again. - A text or video post sent to publish now that never reached the platforms is ruled
failedby the daily check, not before. A photo or document post, and any post sent for later, staysunknownin that case: check history or the platform itself, and if it did not publish, send it again with a newIdempotency-Key. - 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.

