API Basics
Idempotent Requests
Send an Idempotency-Key with a POST so a retried request never runs twice.
A request can time out after the API already acted on it. With an Idempotency-Key, a retry never creates a second post, upload or message.
Send an Idempotency Key
Every POST takes an Idempotency-Key header. Use a new value of up to 255 characters per request, such as a UUID. On a timeout or a dropped connection, send the same request again with the same key.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
idempotencyKey: "5f8d7c2e-1b3a-4e6f-9a0d-2c4b6e8f1a3d",
createPostBody: {
"text": "Release notes are live.",
"accounts": [
{
"accountId": "acc_YOUR_X_ACCOUNT_ID"
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_X_ACCOUNT_ID",
"platform": "x",
"source": "onepostly",
"status": "publishing",
"text": "Release notes are live.",
"mediaKind": "text",
"media": [],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}The SDKs call it idempotencyKey in TypeScript and idempotency_key in Python. Create the key once, such as with randomUUID() or uuid.uuid4(), and reuse it on every retry of the same request.
A key over 255 characters returns 400 VALIDATION_ERROR. Requests without the header run as usual. GET, PATCH and DELETE ignore it.
Replays
A reused key is matched against the first request with that key. Keys belong to the workspace, so all its API keys share them.
| Second request | Response |
|---|---|
| Same method, path and body, within 24 hours | The first response, with Idempotent-Replayed: true |
| Another path or body | 409 IDEMPOTENCY_KEY_REUSED |
| While the first is still running | 409 IDEMPOTENCY_KEY_IN_USE with Retry-After |
| After 24 hours | Runs as a new request |
A replay runs nothing again.
What Is Kept
| First response | Kept | What to do |
|---|---|---|
2xx | Yes | Nothing. A retry gets the same response |
4xx other than 429 | Yes | Fix the request and use a new key |
429 | No | Wait for Retry-After, then retry with the same key |
5xx | No | Retry with the same key |
A kept response replays, errors included. Otherwise the retry runs again.
Errors
| Code | HTTP | Cause | Fix |
|---|---|---|---|
VALIDATION_ERROR | 400 | The key is over 255 characters | Use a shorter key, such as a UUID |
IDEMPOTENCY_KEY_REUSED | 409 | The key was used for another path or body | Use a new key |
IDEMPOTENCY_KEY_IN_USE | 409 | A request with this key is still running | Wait for Retry-After, then retry |
Other codes are in Errors.