GET /v1/projects/:projectId/scheduled-posts
List scheduled posts on a project. Filter by status, window, or account.
/v1/projects/:projectId/scheduled-posts- Auth
- Bearer
- Scope
- publish:read
Enumerate scheduled posts on a project. Useful for populating a queue view in your UI, batch-polling terminal states after a bulk schedule, or reconciling against your own post ledger.
Paginates by cursor. Default sort is scheduledFor descending (most-recent-first), which matches a "recent activity" view - use since/until to window a queue.
projectIdstringrequiredProject whose posts you want.
statusstring | string[]optionalOne of queued, publishing, draft, published, failed, canceled. Repeat the parameter (e.g. `?status=queued&status=publishing`) to filter on multiple statuses.socialAccountIdstringoptionalScope to one connected account.sincestring (ISO 8601, UTC Z)optionalInclusive lower bound on scheduledFor.untilstring (ISO 8601, UTC Z)optionalInclusive upper bound on scheduledFor.cursorstringoptionalOpaque pagination cursor from a previous response.limitintegeroptionaldefault: 50Page size, 1–100.
Example request
curl "https://api.layers.com/v1/projects/prj_254a4ce1-f4ca-42b1-9e36-17ca45ef3d39/scheduled-posts?status=queued&status=publishing&limit=100" \
-H "Authorization: Bearer lp_..."async function* walkAllPending(projectId: string) {
let cursor: string | undefined;
do {
const page = await layers.publishing.listScheduledPosts({
projectId,
status: ["queued", "publishing"],
limit: 100,
cursor,
});
yield* page.items;
cursor = page.nextCursor ?? undefined;
} while (cursor);
}def walk_all_pending(project_id: str):
cursor = None
while True:
page = layers.publishing.list_scheduled_posts(
project_id=project_id,
status=["queued", "publishing"],
limit=100,
cursor=cursor,
)
yield from page["items"]
cursor = page.get("nextCursor")
if not cursor:
returnResponse
{
"items": [
{
"id": "sp_4c8e7d2f-9a1b-4c3d-8e7f-2a1b3c4d5e60",
"containerId": "cnt_8f1d6c3e-4b2a-4a18-9e4f-c2d7a1b0e999",
"socialAccountId": "sa_71b2a4e5-8c3f-4d1a-9e7b-2c5d8f0a1b22",
"platform": "tiktok",
"mode": "publish",
"status": "queued",
"scheduledFor": "2026-04-19T14:00:00Z",
"attemptedAt": null,
"publishedAt": null,
"externalUrl": null
},
{
"id": "sp_7061bc99-4b63-4afb-96ad-408140f4187e",
"containerId": "cnt_9a102945-52bb-4e92-aee3-96ebc7bf09b7",
"socialAccountId": "sa_67857146-69a8-4e23-94cb-499e34ae43e5",
"platform": "instagram",
"mode": "publish",
"status": "published",
"scheduledFor": "2026-04-18T16:00:00Z",
"attemptedAt": "2026-04-18T16:00:11Z",
"publishedAt": "2026-04-18T16:00:29Z",
"externalUrl": "https://www.instagram.com/p/DYgPEhiCeSU/"
}
],
"nextCursor": "cur_01HXZP8K9M4N5P6QRSTU"
}externalUrl for Instagram rows. When platform: "instagram" and
status: "published", externalUrl carries the Graph API permalink
(instagram.com/p/<shortcode> or instagram.com/reel/<shortcode>).
In rare network-blip cases the publisher's optional ?fields=permalink
follow-up fetch fails and externalUrl lands null even though
externalId + publishedAt are populated. TikTok rows always have
externalUrl populated when externalId is — no equivalent edge case.
See GET /v1/scheduled-posts/:id.
Errors
| Status | Code | When |
|---|---|---|
| 422 | VALIDATION | since > until, limit out of range, bad status value. |
| 401 | UNAUTHENTICATED | Missing or invalid key. |
| 403 | FORBIDDEN_SCOPE | Key lacks publish:read. |
| 404 | NOT_FOUND | Project not in your organization. |
See also
POST /v1/content/:id/publish- publish nowPOST /v1/content/:id/schedule- queue for laterGET /v1/scheduled-posts/:id- full status for one postPOST /v1/scheduled-posts/:id/reschedule- rescheduleDELETE /v1/scheduled-posts/:id- cancel while queued