Schedule Post
Schedule a draft for publishing now, at the next open slot, or at a specific time. Requires a paid Creator or Lifetime plan.
POST /v1/posts/{id}/schedule takes an existing draft and either publishes it immediately or places it in the posting queue. publish_at drives the behaviour: 'now' publishes straight to LinkedIn, 'next-slot' resolves the next free slot from the account's posting schedule, and an ISO-8601 timestamp schedules that exact time.
timezone is an IANA name and is required for everything except 'now', because a wall-clock time without a zone is ambiguous. Media can be attached at schedule time with post_type, media_url and media_mime_type if it was not attached to the draft.
Example request
Authenticate with a bearer token in the Authorization header. Create a key on the API page in your LinkedMash settings and export it as LINKEDMASH_API_KEY before running this.
curl -X POST "https://api.linkedmash.com/v1/posts/drf_8f3a21c9/schedule" \
-H "Authorization: Bearer $LINKEDMASH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"publish_at": "next-slot",
"timezone": "Europe/Berlin"
}'Path parameters
The id of the draft to schedule.
Header parameters
Your secret API key as a Bearer token.
Body parameters
'now', 'next-slot', or an ISO-8601 timestamp.
IANA timezone. Required unless publish_at is 'now'.
Media type to attach: text, image, video, or pdf.
Public URL of an image, video, or PDF to attach.
MIME type of the attached media (e.g., 'image/png').
Response
{
"status": true,
"data": {
"ok": true,
"scheduleId": "sch_3a9f81d2",
"runAtUTC": "2026-06-24T08:30:00.000Z"
}
}Response fields
Every response is wrapped in the same envelope: a status flag and a data payload, with meta present where there is pagination or a plan limit to report.
true on success. Every LinkedMash API response carries this envelope flag alongside data, so a client can branch on it without re-reading the HTTP status.
true when the post was queued.
Identifier for the queue entry. This — not the draft id — is what DELETE /v1/queue/{scheduleId} and the reschedule route take.
The resolved publish time in UTC. Worth reading back when you sent next-slot, since that is the only way to learn which slot you got.
Returned instead of scheduleId when publish_at was "now". That branch answers 200 rather than 201.
Choosing between now, next-slot and an explicit time
The three modes have genuinely different failure cases, so pick deliberately rather than defaulting.
Explicit time, for a planned calendar
Send an ISO-8601 publish_at plus an IANA timezone. This is the only mode where you know the publish moment before you call, which is what a content calendar needs.
next-slot, for a queue-driven workflow
Send publish_at as 'next-slot' with a timezone. The route resolves the next free slot from the account's grid and returns runAtUTC — read it back, because that is the only place the chosen time appears.
now, for immediate publishing
Publishes the draft's text straight away and answers 200 with published: true, not 201 with a scheduleId. Media is not attached on this path, and an empty draft is rejected with 400.
Keep the scheduleId
Cancelling and rescheduling both take scheduleId, not the draft id. If you do not store it you have to re-read GET /v1/queue to find it again.
Behaviour and limits
Requires a Creator or Lifetime plan
Everything under /v1/posts, /v1/queue, /v1/schedule, /v1/media and /v1/analytics sits behind one middleware that checks for an unlocked Studio, so a Reader-plan or free key gets 402 with code SUBSCRIPTION_REQUIRED before the handler runs. Bookmark and label reads are on a separate router and are not affected by this gate.
'now' publishes text only, and checks it first
The immediate path reads the draft, extracts its text, and refuses with 400 if it is empty or whitespace. It publishes that text — schedule an explicit time if the post needs media attached.
'next-slot' fails loudly when there is no slot
If the posting schedule yields no free slot the call returns 400 telling you to configure a schedule or pass an explicit time, rather than quietly picking one. Read GET /v1/queue/slots first if you want to know the time in advance.
Returns 201 with a scheduleId
A successful schedule answers 201 with scheduleId and runAtUTC. That scheduleId — not the draft id — is what DELETE /v1/queue/{scheduleId} and the reschedule route take.
'now' returns 200, not 201
The immediate-publish branch answers 200 with { id, published: true }. Branch on the publish_at you sent rather than on the status code.
Errors
Failures carry the same envelope as a success, with the reason in message and a stable machine-readable code where the status alone is ambiguous — several distinct conditions share a 402.