Publish
Create tasks, poll status, submit and retry
All endpoints require a Bearer Token. Base URL is
http://127.0.0.1:19528.
Publishing is asynchronous: creating a task opens one browser view per account, fills the content and (optionally) submits it. The endpoint returns a groupId immediately; poll the status until every target reaches a terminal state.
Create a publish task#
POST /v1/publishRequest body:
| Field | Type | Description |
|---|---|---|
contentType | string | DYNAMIC / VIDEO / ARTICLE / PODCAST |
accountIds | string[] | Target account ids (from Accounts) |
data | object | Content payload; shape depends on contentType (below) |
autoSubmit | boolean | Submit automatically after fill, default false |
Media fields (images, video, cover, audio) accept either form:
- Absolute local path:
"/Users/me/pic.jpg" - http(s) URL:
"https://example.com/pic.jpg"(downloaded locally)
You may also use the object form { "url": "https://…", "name": "cover.jpg" }. blob: URLs are not supported.
data shape per content type#
// DYNAMIC
{ "title": "optional", "content": "body", "images": ["/abs/1.jpg"], "videos": [], "tags": ["tag"] }
// VIDEO
{ "title": "Title", "content": "desc", "video": "/abs/v.mp4", "cover": "/abs/cover.jpg", "tags": [] }
// ARTICLE (markdownContent or htmlContent)
{ "title": "Title", "digest": "summary", "cover": "/abs/cover.jpg", "markdownContent": "# Body", "tags": [] }
// PODCAST
{ "title": "Title", "description": "desc", "audio": "/abs/audio.mp3", "cover": "/abs/cover.jpg", "tags": [] }Example#
curl -X POST 'http://127.0.0.1:19528/v1/publish' \
-H "Authorization: Bearer $MULTIPOST_DESKTOP_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"contentType": "DYNAMIC",
"accountIds": ["a1b2c3d4", "e5f6g7h8"],
"autoSubmit": false,
"data": { "content": "Hello, posted via the API", "images": ["/Users/me/pic.jpg"] }
}'202 Accepted
{
"groupId": "group-…",
"status": {
"taskId": "group-…",
"status": "preparing",
"targets": [{ "platform": "weibo", "accountId": "a1b2c3d4", "status": "pending" }],
"updatedAt": 1733900000000
}
}If a target account's platform does not support the content type, you get 400 unsupported_content_type. Validate with GET /v1/platforms first.
Poll publish status#
GET /v1/publish/{groupId}200
{
"taskId": "group-xxx",
"groupId": "group-xxx",
"status": "publishing",
"open": true,
"targets": [
{ "platform": "weibo", "accountId": "a1b2c3d4", "status": "success", "postUrl": "https://weibo.com/…" },
{ "platform": "xiaohongshu", "accountId": "e5f6g7h8", "status": "failed", "error": "Session expired" }
],
"updatedAt": 1733900012000
}Per-target status: pending / filling / ready / success / failed / cancelled.
success, failed, cancelled are terminal. open indicates whether the group window is still open.
The status snapshot is retained for ~10 minutes after the group closes; after that the query returns 404 publish_not_found.
List open publish groups#
GET /v1/publishSubmit / retry / close#
When autoSubmit=false, targets stop at ready after fill and you confirm submission:
POST /v1/publish/{groupId}/submit # submit all ready targets
POST /v1/publish/{groupId}/targets/{accountId}/submit # submit one account
POST /v1/publish/{groupId}/targets/{accountId}/retry # retry a failed account
DELETE /v1/publish/{groupId} # close the group and its viewsSubmit and retry both return the latest status snapshot (same shape as the status query).
Publish history#
GET /v1/history
GET /v1/history/{id}Optional query params: platform, status (success/failed/pending), limit, offset.