Layers

GET /v1/scheduled-posts/:scheduledPostId

Read one scheduled post's status. Polling or webhooks — either works.

View as Markdown
GET/v1/scheduled-posts/:scheduledPostId
Phase 1stable
Auth
Bearer
Scope
publish:read

Read a scheduled post's current state — whether it's queued, publishing right now, already published (with the external URL), or failed (with an error).

Polling cadence: every 30 seconds while the status is queued, every 5 seconds while publishing, then stop once it reaches a terminal state (published, failed, or canceled). Or subscribe to webhooks to skip polling.

Path
  • scheduledPostId
    stringrequired
    Id returned by schedule or publish.

Example request

curl https://api.layers.com/v1/scheduled-posts/sp_01HXZN4K5M6P7QRS8TUV9WXYZA \
  -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..."
async function waitUntilPublished(id: string) {
  for (;;) {
    const post = await layers.publishing.getScheduledPost({ id });
    if (post.status === "published") return post;
    if (post.status === "failed") throw new Error(post.lastError?.message ?? "publish failed");
    if (post.status === "canceled") throw new Error("canceled");
    await new Promise((r) => setTimeout(r, post.status === "publishing" ? 5000 : 30000));
  }
}
import time

def wait_until_published(post_id: str) -> dict:
    while True:
        post = layers.publishing.get_scheduled_post(id=post_id)
        if post["status"] == "published":
            return post
        if post["status"] in ("failed", "canceled"):
            raise RuntimeError(post.get("lastError", {}).get("message", post["status"]))
        time.sleep(5 if post["status"] == "publishing" else 30)

Response

200Published
{
  "id": "sp_01HXZN4K5M6P7QRS8TUV9WXYZA",
  "containerId": "cnt_01HXZM3K4N5P6QRS7TUV8WXYZ9",
  "socialAccountId": "sa_01HXZ9P2M4N5KLM6TUV7WXYZ9A",
  "platform": "tiktok",
  "mode": "direct_publish",
  "status": "published",
  "externalId": "7385912341234567890",
  "externalUrl": "https://www.tiktok.com/@acmecoffee/video/7385912341234567890",
  "scheduledFor": "2026-04-19T14:00:00Z",
  "attemptedAt": "2026-04-19T14:00:12Z",
  "publishedAt": "2026-04-19T14:00:18Z",
  "canceledAt": null,
  "lastError": null,
  "createdAt": "2026-04-19T13:55:01Z",
  "updatedAt": "2026-04-19T14:00:18Z"
}
200Failed — read lastError
{
  "id": "sp_01HXZN4K5M6P7QRS8TUV9WXYZB",
  "status": "failed",
  "attemptedAt": "2026-04-19T14:00:12Z",
  "publishedAt": null,
  "canceledAt": null,
  "lastError": {
    "code": "CREDENTIAL_INVALID",
    "message": "The social account's token was revoked upstream.",
    "data": { "platform": "instagram", "platformCode": "OAuthException" }
  },
  "createdAt": "2026-04-19T13:55:01Z",
  "updatedAt": "2026-04-19T14:00:25Z"
}

Status values

statusTerminal?Meaning
queuednoWaiting for scheduledFor, or waiting on approval.
publishingnoLayers is actively uploading media and calling the platform API.
draft_in_inboxyesmode: draft_to_device — draft landed in the user's mobile app; they finish by tapping post. Terminal from Layers' side.
publishedyesexternalId and externalUrl are populated.
failedyeslastError is populated.
canceledyesYou or a token revocation canceled it.

Errors

StatusCodeWhen
401UNAUTHENTICATEDMissing or invalid key.
403FORBIDDEN_SCOPEKey lacks publish:write.
404NOT_FOUNDPost not in your organization.

See also

On this page