Publish precheck
Dry-run a piece of copy + media per platform and per account, without writing or publishing: text length, media specs, account authorization, 24-hour rate caps, TikTok / YouTube required fields. Same rules as a real publish; only ok=true is worth sending. Manual channels warn but never block.
/api/v1/posts/precheckAuthorization & guardrails
- Send
Authorization: Bearer <credential>; credentials are issued under Settings → Integrations → Long-lived credentials, see Authentication. - The credential needs scope
posts:read; the issuer's workspace role must also allow the action. - Rate limit: read tier, 60/min per credential; over the cap returns 429 with
Retry-After. - Idempotency: read endpoint, no Idempotency-Key needed.
- Read-only: writes nothing and sends nothing out.
Request body (application/json)
platformsstring[] (enum: x · youtube · instagram · tiktok · facebook · threads · douyin · xiaohongshu · wechat_mp)requiredTarget platforms, at least one.
contentstringrequiredMain copy; may be empty when every platform has a variant.
titlestringoptionalTitle (required for YouTube).
variantsobject[] { platform, content?, title? }optionalPer-platform overrides; the check measures override ?? main copy.
targetAccountIdsstring[]optionalTarget accounts; omit = all usable accounts per platform, max 20.
mediaobject[] { kind, url, bytes?, durationSec? }optionalkind is image / video; url must be a popkit storage URL.
tiktokOptionsobject { privacyLevel? }optionalprivacyLevel must be chosen by a person for TikTok.
threadsOptionsobject { linkAttachment? }optionalA text-only Threads post's link card counts toward the 5-link limit.
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.
| Status | Possible codes |
|---|---|
| 400 | invalid_input |
| 401 | unauthenticated |
| 403 | forbidden / workspace_not_found |
| 404 | not_found |
| 429 | rate_limited |
| 500 | internal |
Examples
curl -X POST "https://popkit.loxily.com/api/v1/posts/precheck" \
-H "Authorization: Bearer popkit_it_••••••••" \
-H "Content-Type: application/json" \
-d '{
"platforms": [
"x",
"youtube"
],
"content": "本周更新速览",
"title": "本周更新速览",
"media": [
{
"kind": "video",
"url": "https://storage.googleapis.com/…/weekly.mp4",
"bytes": 48213000,
"durationSec": 62
}
]
}'{
"data": {
"ok": false,
"platforms": [
{
"platform": "x",
"blocker": null,
"accounts": [
{
"accountId": "acc_01J8XQ5M9V2R",
"handle": "@popkit",
"textMax": 280,
"ok": true,
"error": null,
"warning": null
}
],
"expiredAccounts": []
},
{
"platform": "youtube",
"blocker": "needs_reauth",
"accounts": [],
"expiredAccounts": [
{
"accountId": "acc_01J8Z…",
"handle": "popkit 频道"
}
]
}
]
},
"meta": {
"requestId": "6a1d0c9e-2b7f-4e3a-8c5d-1f0e9b8a7c66"
}
}