Posts

Update a post

Edit an existing post and choose its tier (same rules as create). Only drafts, rejected and scheduled posts can be edited; posts in review are locked and published posts are immutable. Omitting media / targetAccountIds keeps the current values; an empty list clears them.

PATCH/api/v1/posts/{postId}
posts:writeschedule:writepublish:executewrite / publish tierIdempotency-Key optional, required for publish

Authorization & guardrails

  • Send Authorization: Bearer <credential>; credentials are issued under Settings → Integrations → Long-lived credentials, see Authentication.
  • The credential needs scope posts:write / schedule:write / publish:execute (any one lets you call it; which tier you may use is decided by the credential's publish allow-list); the issuer's workspace role must also allow the action.
  • Rate limit: write tier 10/min; with action: "publish" the publish tier applies, 5/min (per credential).
  • Idempotency: optional for draft / schedule; required with action: "publish".

Path parameters

postIdstringrequired

Post id.

Request body (application/json)

actionenum: draft · schedule · publishrequired

Tier after this edit; same meaning as on create.

contentstringrequired

Main copy; may be an empty string when every target platform has its own copy in variants.

platformsstring[] (enum: x · youtube · instagram · tiktok · facebook · threads · douyin · xiaohongshu · wechat_mp)required

Target platforms.

titlestringoptional

Title (required for YouTube).

targetAccountIdsstring[]optional

Omit = keep the current selection; a list replaces it; an empty list = back to "all usable accounts".

scheduledAtdatetime (ISO 8601, with timezone)optional

Required for schedule; must carry a timezone (Z or ±HH:MM) and be at least 60 s in the future; on a draft it is only the planned date on the calendar.

mediaobject[] { kind, dataUrl, platform?, durationSec? }optional

Omit = keep existing media; empty list = clear. kind is image / cover / video; dataUrl must be a popkit storage URL (get one via POST /v1/media), image data URLs are accepted for images / covers; platform marks a per-platform override.

variantsobject[] { platform, content?, title? }optional

Per-platform copy overrides; send only the platforms that differ.

tiktokOptionsobjectoptional

Omit = keep existing settings; null = clear. TikTok Direct Post compliance options: privacyLevel (must be chosen by a person when posting to TikTok), allowComment, allowDuet, allowStitch, commercial, yourBrand, brandedContent, coverTimestampMs.

youtubeOptionsobject { categoryId?, madeForKids?, playlistId? }optional

Omit = keep existing settings; null = clear. YouTube category, made-for-kids flag, and the id of a playlist to add the video to after publishing (must belong to the target channel; system lists such as Watch Later are unavailable; a failed add does not fail the publish).

threadsOptionsobject { replyControl?, topicTag?, linkAttachment?, replyApprovals? }optional

Omit = keep existing settings; null = clear. Threads options: replyControl — who can reply (everyone / followers_only / accounts_you_follow / mentioned_only / parent_post_author_only; default everyone); topicTag — topic tag (1–50 characters, no '.' or '&'); linkAttachment — link card (an http(s) URL; text-only posts only; counts toward the 5-link limit); replyApprovals — reply approvals (true = replies from others stay hidden until the author approves them; default off).

clientRequestIdstringoptional

Idempotency key (8–128 chars of [A-Za-z0-9_.:-]); prefer the Idempotency-Key header, which wins over the body. Required for the publish tier.

Responses

Success is HTTP 200 with a { data, meta } envelope; examples per status are on the right (at the end of the page on narrow screens). Every error is { error: { code, message, params }, meta } — branch on the code, not the message; see Errors.

StatusPossible codes
400invalid_input
401unauthenticated
402plan_limit
403forbidden / workspace_not_found
404not_found
409no_account / needs_reauth / replay
429rate_limited
500internal
502platform_error
503external_writes_off

Examples

Request
curl -X PATCH "https://popkit.loxily.com/api/v1/posts/pst_01J8ZK3R7QW6M2" \
  -H "Authorization: Bearer popkit_it_••••••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: acme-2026-09-21-001" \
  -d '{
  "action": "schedule",
  "content": "文案改了一版 ✨",
  "platforms": [
    "x",
    "instagram"
  ],
  "scheduledAt": "2026-09-22T09:30:00+08:00"
}'
Response
Scheduled
{
  "data": {
    "postId": "pst_01J8ZK3R7QW6M2",
    "status": "scheduled",
    "scheduledAt": "2026-09-21T10:00:00.000Z",
    "deepLink": "https://popkit.loxily.com/calendar?post=pst_01J8ZK3R7QW6M2"
  },
  "meta": {
    "requestId": "3f9c1e2a-7d4b-4c1e-9a6f-0b2d8e5c7a11"
  }
}