Skip to content
Reading with an AI assistant?View as MarkdownOpen in ClaudeOpen in ChatGPT

Guides

Publish to X with the API

X uses the same POST /v1/posts call. The x overrides cover quoting another post, who can reply, AI-media disclosure, paid partnership and a first-comment reply.

Browse docs

6 min read

What do you need before you publish?#

You need one connected account for the platform. Connect it in the SkedCast console. If a client owns the account, create a connect link with POST /v1/clients/{id}/connect-invites and send it to them. They authorize from that page without a SkedCast login.

GET /v1/accounts lists the connected accounts with their ids. Pass that id in targets.accountIds below.

How do you schedule a X post with the API?#

bash
curl -X POST https://api.skedcast.com/v1/posts \
  -H "Authorization: Bearer sked_live_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "<clientId>",
    "content": "Launch day is here 🚀",
    "mediaIds": ["<mediaAssetId>"],
    "targets": { "mode": "selection", "accountIds": ["<xAccountId>"] },
    "schedule": { "type": "at", "scheduledAt": "2030-01-15T15:00:00Z" }
  }'
A minimal X post, scheduled for a specific time.

Which X fields can you set?#

Put everything platform-specific in one variants entry with "platform": "x" and an overrides object. Send only x keys on a x variant. SkedCast reads the keys in the table below and ignores the rest.

FieldTypeValues / defaultNotes
quoteTweetIdstring—The id of the post to quote.
replySettingsenumfollowing \| mentionedUsers \| subscribers \| verifiedOmit for X's default (everyone can reply).
madeWithAibooleanfalseDiscloses AI-generated or altered media. Independent of the post-level aiDisclosure field.
paidPartnershipbooleanfalseDiscloses a paid partnership or branded content.
firstCommentstring—Posted as a reply from the same account right after publish. Best-effort: a failed comment never fails the post. The outcome is reported as firstCommentIssue on GET /v1/post-targets/{id}.
pollOptionsstring[] (or a comma-separated string)2–4, up to 25 characters eachTurns the post into a poll. A poll cannot be combined with media.
pollDurationMinutesinteger5–10,080 (default 1,440)How long the poll stays open, in minutes.

How do you add X-specific settings?#

json
{
  "clientId": "<clientId>",
  "content": "Shipped: bulk import now handles 5,000-row CSVs.",
  "mediaIds": [],
  "targets": { "mode": "selection", "accountIds": ["<xAccountId>"] },
  "variants": [
    { "platform": "x", "overrides": { "replySettings": "following" } }
  ],
  "schedule": { "type": "at", "scheduledAt": "2030-01-15T15:00:00Z" }
}
The same POST /posts body, with a variants entry added.

How do you check that the post published?#

Publishing creates one post target per account. GET /v1/post-targets/{id} (or GET /v1/posts/{id}) reports status, plus externalId (X's own post id) and permalink (its public URL) once published. To avoid polling, subscribe to the target.published and target.failed webhooks (see the webhooks guide).

xtwitterapipublish

FAQ

How do I post several connected posts as a thread?
Use the post-level thread field: { segments: [{ content, mediaIds }, …] } with 2–50 entries. Segment 0 is the head post and every later segment replies to the one before it. On thread-capable platforms (X, Bluesky and Threads) the top-level content is ignored in favor of segments.

Ready to broadcast everywhere?

Sign up free — no credit card. You land on the Free plan, and you can start a one-time 7-day Studio trial from your workspace whenever you are ready. Connect your first accounts, import a batch, and watch one post fan out across every platform.