Skip to content

Posts

A post is one piece of content published to one or more accounts. Every account you target gets its own result, so one post to Instagram and Facebook can succeed on one and fail on the other.

Method Path Body / query Returns
POST /v1/posts create body, see below. ?wait=true optional 201 post
GET /v1/posts query: workspace, status, from, to, external_ref, page, limit list
GET /v1/posts/:id post
PATCH /v1/posts/:id any of caption, media, targets, schedule_at, options, external_ref post
DELETE /v1/posts/:id 204. Cancels a scheduled post, never deletes on the network
POST /v1/posts/:id/publish ?wait=true optional post. Publishes now
{
"workspace": "ws7k2m9p4q1r8t3",
"caption": "Fresh cuts, Friday walk-ins welcome",
"media": ["med9x2c4v6b8n1m"],
"targets": ["acig4h2k5m7p9r1", "acfb8n2c4v6b1m3"],
"schedule_at": "2026-09-01T09:00:00Z",
"external_ref": "acme:post:1234",
"options": {
"instagram": { "media_type": "IMAGE", "first_comment": "#salon #friday", "share_to_feed": true },
"facebook": { "link": "https://salonnova.example/book" }
},
"status": "draft"
}
Field Required Notes
workspace yes The workspace that owns the targets and media
caption yes for Facebook text posts, otherwise optional The text. Can be overridden per target
media Instagram: at least one. Facebook: optional Media ids from this workspace, in display order. Two to ten images make an Instagram carousel
targets yes, at least one Account ids, or objects with a caption override, see below
schedule_at no ISO-8601 UTC. Present: the post is scheduled. Absent: it publishes now
external_ref no Your own id for this post. Comes back in every webhook and is filterable on GET /v1/posts
options no Per-network settings, see below
status no "draft" to save without publishing or scheduling

What happens on create:

  • No schedule_at and no status: "draft": the post publishes immediately. The call returns at once with status: "publishing"; the outcome arrives by webhook or by polling. Add ?wait=true to hold the request for up to 25 seconds and get the final post back instead.
  • schedule_at set: the post is scheduled and goes out at that time.
  • status: "draft": the post is saved and nothing else happens until you patch a schedule_at on it or call POST /v1/posts/:id/publish.

Validation runs before anything is stored. Targets must be active accounts in the workspace, media ids must exist in the workspace, and Instagram targets must have media. Failures return validation_error with field, or account_disconnected when a target cannot be used.

targets accepts plain account ids, objects, or a mix. An object overrides the caption for that account:

{
"caption": "Fresh cuts, Friday walk-ins welcome. Book at the link.",
"targets": [
{ "account": "acig4h2k5m7p9r1", "caption": "Fresh cuts, Friday walk-ins welcome. Link in bio." },
"acfb8n2c4v6b1m3"
]
}

The Instagram target gets its own caption. The Facebook target uses the post-level caption.

options is keyed by network and applies to every target on that network.

Network Option Notes
instagram media_type IMAGE, CAROUSEL or REELS. Derived from media when omitted: one image is IMAGE, several are CAROUSEL, a video is REELS
instagram first_comment Posted as the first comment right after publishing. The usual place for hashtags
instagram share_to_feed Reels only. true shows the Reel on the profile grid as well
facebook link A URL to attach. With no media the post becomes a link post with a preview

Unknown options are rejected with validation_error.

POST /v1/posts?wait=true and POST /v1/posts/:id/publish?wait=true hold the request until the post is done or 25 seconds have passed. Images normally finish inside that window. Reels often do not: Meta processes the video first, and the response then comes back with status: "publishing". Treat publishing as “not finished yet” and rely on the webhook or a poll for the final state.

{
"id": "pst5g7j9l2n4q6s",
"workspace": "ws7k2m9p4q1r8t3",
"external_ref": "acme:post:1234",
"caption": "Fresh cuts, Friday walk-ins welcome",
"media": [{ "id": "med9x2c4v6b8n1m", "kind": "image", "mime": "image/jpeg", "width": 1080, "height": 1350 }],
"targets": [
{
"account": "acig4h2k5m7p9r1",
"network": "instagram",
"username": "salonnova",
"status": "published",
"platform_post_id": "17900000000000001",
"permalink": "https://www.instagram.com/p/C_abc123/",
"error": null,
"published_at": "2026-08-25T09:20:11Z"
},
{
"account": "acfb8n2c4v6b1m3",
"network": "facebook",
"username": "salonnova",
"status": "failed",
"platform_post_id": null,
"permalink": null,
"error": "(#200) The user hasn't authorized the application to perform this action",
"published_at": null
}
],
"schedule_at": null,
"status": "partial",
"published_at": "2026-08-25T09:20:11Z",
"attempts": 1,
"last_error": "facebook: (#200) The user hasn't authorized the application to perform this action",
"created_by": "api",
"created": "2026-08-25T09:19:58Z",
"updated": "2026-08-25T09:20:11Z"
}
Field Notes
media The media objects, in order, as they were at creation
targets[].status pending until the network answers, then published or failed
targets[].platform_post_id, permalink Meta’s id and the public URL once published
targets[].error Meta’s error text for a failed target
status draft, scheduled, publishing, published, partial, failed or canceled. Lifecycle in Scheduling
attempts How many publish runs the post has had
last_error The most recent failure across targets, prefixed with the network
created_by api, embed, dashboard or mcp

GET /v1/posts with any of:

Query Notes
workspace Filter to one workspace. Required with a partner key if you do not want the whole partner
status One status
from, to ISO-8601 bounds on schedule_at, falling back to created for posts without a schedule. This is what a calendar view uses
external_ref Exact match on your id
page, limit Pagination, default 50, max 200
Terminal window
curl "https://social.missless.tel/v1/posts?workspace=ws7k2m9p4q1r8t3&status=scheduled&from=2026-09-01T00:00:00Z&to=2026-09-30T23:59:59Z" \
-H "Authorization: Bearer $MISSLESS_API_KEY"

PATCH /v1/posts/:id accepts caption, media, targets, schedule_at, options and external_ref. It works on posts in draft, scheduled or failed. Anything else returns conflict (409): a post that is publishing or already published cannot be edited through MissLess, and MissLess never edits on the network.

Terminal window
curl -X PATCH https://social.missless.tel/v1/posts/pst5g7j9l2n4q6s \
-H "Authorization: Bearer $MISSLESS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "schedule_at": "2026-09-02T09:00:00Z" }'

Patching schedule_at onto a draft moves it to scheduled. Patching a failed post lets you fix the reason before calling publish again.

DELETE /v1/posts/:id returns 204. On a scheduled post it cancels the schedule and the post shows canceled. On a draft it removes it. On a published post it removes only the MissLess record; the content stays on the network. Nothing is ever deleted on Facebook or Instagram through this API.

POST /v1/posts/:id/publish publishes a draft, scheduled or failed post immediately. On a failed post it is a retry and increments attempts. Add ?wait=true to wait for the result.

Terminal window
curl -X POST "https://social.missless.tel/v1/posts/pst5g7j9l2n4q6s/publish?wait=true" \
-H "Authorization: Bearer $MISSLESS_API_KEY"