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 requestResponse
Same method, path and body, within 24 hoursThe first response, with Idempotent-Replayed: true
Another path or body409 IDEMPOTENCY_KEY_REUSED
While the first is still running409 IDEMPOTENCY_KEY_IN_USE with Retry-After
After 24 hoursRuns as a new request

A replay runs nothing again.

What Is Kept

First responseKeptWhat to do
2xxYesNothing. A retry gets the same response
4xx other than 429YesFix the request and use a new key
429NoWait for Retry-After, then retry with the same key
5xxNoRetry with the same key

A kept response replays, errors included. Otherwise the retry runs again.

Errors

CodeHTTPCauseFix
VALIDATION_ERROR400The key is over 255 charactersUse a shorter key, such as a UUID
IDEMPOTENCY_KEY_REUSED409The key was used for another path or bodyUse a new key
IDEMPOTENCY_KEY_IN_USE409A request with this key is still runningWait for Retry-After, then retry

Other codes are in Errors.