Chirio
Get Started
Introduction
Quickstart
How Chirio works
Authentication
Platforms
Overview
Instagram
Threads
X
LinkedIn
Supa Hub
Guides
Connect accounts
Publish a post
Media requirements
Carousels
First comments
Idempotency and retries
Account lifecycle
Revocation and deletion
The dashboard
Billing
Plans
Metering
Quotas
Api Reference
Overview
Accounts
Posts
Errors
Changelog
Roadmap
TrademarkTrademark
Ctrl k
Search…
Sign up
Chirio
Get Started
Introduction
Quickstart
How Chirio works
Authentication
Platforms
Overview
Instagram
Threads
X
LinkedIn
Supa Hub
Guides
Connect accounts
Publish a post
Media requirements
Carousels
First comments
Idempotency and retries
Account lifecycle
Revocation and deletion
The dashboard
Billing
Plans
Metering
Quotas
Api Reference
Overview
Accounts
Posts
Errors
Changelog
Roadmap
TrademarkTrademark© Dopler. All rights reserved.
Built with Aveiro

Idempotency and retries

Make a timed-out publish safe to send again, and know what a replayed response actually means.
Updated 1mo ago
First comments
Account lifecycle
Publishing is synchronous and can run for minutes on video. A network failure or client timeout leaves you unable to tell whether the post went out. An idempotency key removes the question.
curl -X POST "$CHIRIO/api/v1/posts" \
  -H "Authorization: Bearer $CHIRIO_API_KEY" \
  -H "Idempotency-Key: release-2-4-0" \
  -H "Content-Type: application/json" \
  -d '{ "content": "...", "platforms": [ ... ] }'
Or in the body — the body field wins if both are present:
{ "idempotencyKey": "release-2-4-0", "content": "...", "platforms": [] }
Keys are 1–255 characters and scoped per project, so two tenants can use the same string without colliding.

What a retry does

Attempt
Status
Body
First`201` — or `202` if you sent `publishAt``replayed: false`
Retry with the same key`200``replayed: true`, the original post
Retrying never publishes twice. The post row carrying the key is inserted before any platform call, and a unique index on (project, key) means a concurrent duplicate loses the insert race and is answered with the original post instead.

A replayed response is a snapshot, not a promise

Replayed targets may not be final
A replay returns the stored per-target state at that moment. If the original request is still running — video processing, a slow carousel — some targets will still be pending. Poll GET /api/v1/posts/:id until they settle.
let { post, replayed } = await publish();

while (replayed && post.targets.some((t) => t.status !== "published" && t.status !== "failed")) {
  await new Promise((r) => setTimeout(r, 5_000));
  ({ post } = await fetch(`${CHIRIO}/api/v1/posts/${post.id}`, { headers }).then((r) => r.json()));
}
A scheduled post replays the same way, and its targets stay pending until its time comes — so poll on a schedule of your own rather than in a tight loop.

Choosing a key

Derive it from the logical post, not from the attempt:
  • Good: release-2-4-0, campaign-42-slot-3, a UUID stored with your own draft record.
  • Bad: a fresh crypto.randomUUID() per attempt — that is no key at all.
Use a new key when retrying failed targets
Reusing the key returns the original post untouched. To republish targets that failed, send a fresh request with only those accountIds and a NEW idempotency key — usage is recorded per target that actually published, so retrying the third of three targets bills one write.
Rescheduling works the same way. A scheduled post is immutable, so moving one is followed by a fresh create — with a key, since the old one would just hand back the post you cancelled.
POST /posts/:id/cancel
new

What is not idempotent — and what does not need a key

Only POST /api/v1/posts takes an idempotency key. POST /api/v1/accounts/connect mints a new single-use OAuth state each call by design — an authorize URL that could be replayed would be a security problem, not a convenience.
The repost endpoints need no key because they carry one implicitly. A repost of a published target is billed once per target; a repost of any other post URL is billed once per account and post. Calling either twice reaches the platform twice — where a repeat retweet is a no-op — and bills once. See Metering.