Creating posts
One request creates one post per target account. Each is an independent post with its own schedule and its own outcome; they share only a campaign id.
https://antwork.io/api/v1/postsScopewrite · publishRequest
curl https://antwork.io/api/v1/posts \
-H "Authorization: Bearer $ANTWORK_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"accounts": ["acc_linkedin", "acc_x"],
"text": "Shipped the API today.",
"scheduledFor": "2026-10-01T09:00:00Z"
}'Response
The answer is 202 Accepted, never 200. Nothing publishes inside the request: a post is queued and a worker sends it, so the response tells you what was accepted rather than what was published.
{
"object": "post_batch",
"campaignId": "b3f1...",
"posts": [
{
"object": "post_result",
"id": "pQ7x...",
"accountId": "acc_linkedin",
"platform": "linkedin",
"status": "accepted",
"reason": null,
"message": null
},
{
"object": "post_result",
"id": null,
"accountId": "acc_x",
"platform": "x",
"status": "rejected",
"reason": "text_too_long",
"message": "@antwork: Text exceeds x character limit"
}
]
}202 can contain rejections. Read every entry in posts, not just the status code. Only when nothing at all was accepted is the answer a 400, and the array still ships with it.What each target status means
accepted— written, and scheduled (or saved, for a draft). Poll the id to see what happened.rejected— refused before anything was written. Nothing exists; fixreasonand send again.failed— the post was created but could not be scheduled. It exists and will not go out.
Scheduling
Omit scheduledFor to publish immediately. Supply an ISO 8601 time to schedule, at most 30 days ahead. The queue behind this will not accept a task further out, and the error names the latest time it will take. A time in the past is refused with scheduled_for_in_past.
Request body
accountsstring[]requiredGET /api/v1/accounts, at most 25. One post is created per account.textstringtexts.textsobjecttext for that account. Use it when one platform needs a shorter version.mediastring[]media_not_hosted rather than accepted and then failed at publish time. Uploading through the API is not available yet.scheduledForISO 8601draftbooleantrue creates a draft and sends nothing, and needs only the write scope. Anything else creates a post that will go out, which needs publish.optionsobjectworkspaceIdstringworkspace_required. Every account must belong to it.campaignIdstringplatform_not_available, and the rest of the request goes ahead. GET /api/v1/accounts lists every connected account, so check platform before sending.Platform options
Anything platform-specific goes in options, keyed by platform and applied to every account of that platform in the request. Only the platforms listed here accept options through the API.
| Platform | Accepts |
|---|---|
| accepts no options | |
| x | communityId, shareWithFollowers |
{
"accounts": ["acc_x"],
"text": "Shipped the API today.",
"options": {
"x": { "communityId": "1493446837214", "shareWithFollowers": true }
}
}400 naming the field, not a post that quietly goes out without the setting you asked for.Idempotency
Send an Idempotency-Key header with every create, so a retry cannot post twice. How the key behaves is on the Idempotency page. Idempotency →