Getting started
Send an Idempotency-Key so a retried create returns the original result instead of a second post, message, call or ad.
Networks drop responses. A job runner retries a step, a no-code tool fires a node twice, a user double-clicks. Without protection, each of those can publish the same post twice or send the same SMS twice. The Idempotency-Key header stops that: Pozy remembers the result of the first request with a given key and hands it back for any repeat.
#Send a key on creates
Generate one key per logical action, store it next to the job, and send the same key on every attempt.
curl -X POST https://api.pozy.ai/v1/posts \
-H "Authorization: Bearer $POZY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0b6f1c2e-7a43-4d8e-9f15-3c2a8e4b7d91" \
-d '{
"content": "Doors open at 9.",
"platforms": [{ "platform": "linkedin", "accountId": "6720f41a8d3be96c1e5a02f7" }],
"scheduledFor": "2026-11-05T09:00:00",
"timezone": "Europe/London"
}'import { randomUUID } from "node:crypto";
const key = job.idempotencyKey ?? (job.idempotencyKey = randomUUID()); // persist with the job
const res = await fetch("https://api.pozy.ai/v1/posts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Idempotency-Key": key,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "Doors open at 9.",
platforms: [{ platform: "linkedin", accountId: "6720f41a8d3be96c1e5a02f7" }],
scheduledFor: "2026-11-05T09:00:00",
timezone: "Europe/London",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);import os, uuid, requests
key = job.get("idempotency_key") or str(uuid.uuid4()) # persist with the job
resp = requests.post(
"https://api.pozy.ai/v1/posts",
headers={
"Authorization": f"Bearer {os.environ['POZY_API_KEY']}",
"Idempotency-Key": key,
},
json={
"content": "Doors open at 9.",
"platforms": [{"platform": "linkedin", "accountId": "6720f41a8d3be96c1e5a02f7"}],
"scheduledFor": "2026-11-05T09:00:00",
"timezone": "Europe/London",
},
timeout=30,
)Rules for keys:
- Any string up to 255 characters. A UUID v4 is the simplest choice. A longer key returns
400. - One key per action. Reusing a key for a different post returns the first post, not a new one.
- Keys are remembered for 24 hours and are scoped to your workspace.
- Generate the key before the first attempt, not inside the retry loop.
#What a repeat returns
For posts, the first request creates the post and returns 201. A repeat with the same key within 24 hours creates nothing and returns 200 with the original post, even if the body changed in between. Treat both as success.
{
"message": "Post already exists (idempotent retry)",
"post": { "_id": "6721a0c47b2e5f9d3a18c6e0", "status": "scheduled" }
}If the first request is still being processed when the repeat arrives, you get 409 with code: "idempotency_conflict" and a Retry-After header. Wait that long and send the same request again.
For the other endpoints below, only successful responses are remembered. If the first attempt failed, the key is released and the retry runs for real. The same key sent to a different path, or with a different body, returns 422.
#Endpoints that accept a key
| Area | Endpoints |
|---|---|
| Publishing | Create post, create blog article |
| Inbox | Send message, reply to comments, reply to a review |
| Phone and messaging | Send SMS, send RCS message, create RCS agent, start a voice call, start a WhatsApp call |
| Branded calling | Create enterprise, create identity |
| Ads | Create campaign, create ad set, create ad, boost a post, messaging ad, call ad, and the duplicate endpoints for campaigns, ad sets and ads |
| Creator campaigns | Create campaign, raise budget, add participant, approve, reject or reopen a submission, adjustments, payout batches |
| Money | Top-ups and transfers |
| Support | Ask the support assistant |
The API reference lists Idempotency-Key under the header parameters of every endpoint that takes it. Other writes are either updates (sending them twice leaves the same result) or cheap to check first.
To make profile creation retry-safe, set externalId to your own customer id. A second create with the same externalId returns 409 with code: "profile_external_id_conflict" and the existing profile's id in details.existingProfileId, so you can carry on with that profile (profiles).
#Duplicate content protection
Separately from keys, Pozy refuses to publish the exact same content to the same account twice within 24 hours. A match on the account, the text and the media URLs returns 409:
{
"error": "This exact content is already scheduled, publishing, or was posted to this account within the last 24 hours.",
"details": {
"accountId": "6720f41a8d3be96c1e5a02f7",
"platform": "linkedin",
"existingPostId": "6721a0c47b2e5f9d3a18c6e0"
}
}Only scheduled, publishing and published targets count. Failed and cancelled ones do not. To repost on purpose, change the text, the media or the account.
If you send your own x-request-id and a retry carries the same request id and the same content, Pozy treats it as a retry and returns the original post rather than this 409. Idempotency-Key is still the better tool: it works even when the body changes.
#A safe retry recipe
- Create the key and save it with your job before the first attempt.
- Send the request with the key.
- On a timeout, a connection error,
429or5xx: wait (honourRetry-After, otherwise back off 1 s, 2 s, 4 s...), then send the identical request with the same key. - On
200or201: store the returned id. You are done. - On
409 idempotency_conflict: waitRetry-Afterand go back to step 3. - On any other
4xx: stop and fix the request. Retrying will not help.
In n8n, Make or Zapier, create a fresh key per HTTP step. One key shared by several steps turns every step after the first into a "retry" of the first, and nothing else gets created.