OpenAPI reference · Posts
Update a post (content, status, schedule)
/posts/{postId}Partial update of a post. Any subset of content, title,
contentType may be sent. Sending content on a post that has
no internal name yet names it after its own opening line;
sending title sets the name explicitly and nothing overwrites
it afterwards. Status can be changed via either
statusCategory (move to the workspace's default status in
that lifecycle category) or an explicit statusId (from
GET /post-statuses) — the two are mutually exclusive.
Scheduling is driven by scheduledFor:
- A future ISO timestamp schedules (or reschedules) the
post. Before scheduling, the project's LinkedIn connection
is verified: no access token on file is an immediate
refusal, otherwise a live
/meping + token refresh for personal brands (non-empty admin set for company pages). If LinkedIn isn't usable the request fails409 conflictwithdetails.reason/details.reconnectUrl/details.retryable: false, and the post is left unchanged. nullunschedules the post (reverts to a draft and clears its calendar slot).- Omitting the field leaves the schedule untouched.
Emits post.updated, plus post.scheduled / post.unscheduled
when the schedule changes.
There is no REST delete: removing a post is MCP-only
(delete_post), two-phase, and rides posts:destroy — a scope
no alias and no posts:write grant ever implies. It emits
post.deleted. Deleting a published
post removes only Scripe's copy; the LinkedIn post stays live
and its analytics history is kept but stops linking back.
Required scope: posts:write.
Authorization
AuthorizationstringrequiredBearer token in the Authorization header.
Pass
Authorization: Bearer scripe_sk_live_<...>(orscripe_sk_test_<...>for test keys) on every request. Keys are scoped to a single workspace and can be revoked from the Scripe dashboard.The same header also accepts an OAuth 2.1 access token (
scripe_oat_*); both credentials share one scope vocabulary and every operation below documents the scope it requires. An API key can hold every scope named on this surface exceptwebhooks:manage, which is grantable to OAuth tokens only today — the webhook-endpoint operations answer403 scope_missingto every API key. Operations that name no scope accept any valid token of the workspace.
Path parameters
postIdstringrequired
Header parameters
Scripe-Api-VersionstringPin the API version. Format
YYYY-MM-DD. Omit to receive the currently rolling default. Unknown versions return400 version_unsupported.Idempotency-KeystringOpaque string (1–64 chars,
[A-Za-z0-9_-]) used to dedup retried writes. Within 24h of the first request, the same key- same body returns the original response (
Idempotent-Replayed: true). Same key + different body returns409 idempotency_key_conflict.
Strongly recommended for every write — see
/docs/api/v1/idempotency.- same body returns the original response (
Request bodyapplication/json
contentstringtitlestringThe post's INTERNAL name. Unlike on create, omitting it and sending
""differ here: omit it to keep a name YOU set (a still-unnamed post is named from thecontentyou send, and a name Scripe derived keeps following your opening line until you rewrite it), or send""to clear the name and return the post to being unnamed and Scripe-nameable.contentTypestringAllowed values:
PERSONAL,BUSINESS_INTERNAL,BUSINESS_EXTERNAL,EDUCATIONAL,UNKNOWNstatusCategorystringMove the post to the workspace's default status in this lifecycle category. Mutually exclusive with
statusId.Allowed values:
suggested,draft,inProgress,review,scheduled,publishedstatusIdstringMove the post to a specific custom status by id (from
GET /post-statuses). Mutually exclusive withstatusCategory.scheduledForstring <date-time> | nullFuture ISO timestamp to schedule/reschedule the post (LinkedIn connection verified first).
nullunschedules. Omit to leave unchanged.Offset-less timestamps resolve in the project's calendar timezone; a bare date is rejected. See
PostCreate.scheduledFor.autoLikebooleanEnable auto-like engagement when the post goes live.
autoCommentbooleanEnable auto-comment engagement when the post goes live.
Responses
- 200
Post updated.
- 400
Malformed request (bad cursor, bad limit, etc.).
- 401
Missing, malformed, expired, or revoked API key.
- 403
Plan not eligible, scope missing, or workspace mismatch.
- 404
Resource not found in this workspace.
- 409
Either an
Idempotency-Keyconflict, or LinkedIn is not connected for the post's project (cannot schedule). - 422
Body shape was JSON but failed validation (
unprocessable). - 429
Sliding-window rate limit exceeded.
Example request
curl --request PATCH \
--url 'https://api.scripe.io/v1/posts/{postId}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"content": "string",
"title": "string",
"contentType": "PERSONAL",
"statusCategory": "suggested",
"statusId": "string",
"scheduledFor": "2026-08-18T09:00:00+02:00",
"autoLike": true,
"autoComment": true
}'Example response (200)
{
"data": {
"id": "post_a1b2c3d4e5f6g7h8",
"projectId": "string",
"status": "waitingProcessing",
"statusId": "string",
"statusTitle": "string",
"statusCategory": "suggested",
"platform": "string",
"contentType": "string",
"funnelStage": "REACH",
"title": "string",
"content": "string",
"contentTruncated": true,
"scheduledAt": "2026-08-10T09:00:00Z",
"publishedAt": "2026-08-10T09:00:00Z",
"lastPublishError": "string",
"lastPublishAttemptAt": "2026-08-10T09:00:00Z",
"delivery": {
"state": "not_scheduled",
"willRetry": true,
"retryUntil": "2026-08-10T09:00:00Z",
"detail": "string"
},
"review": {
"state": "not_requested",
"awaitingDecision": true,
"reviewerUserId": "string",
"deadline": "2026-08-10T09:00:00Z",
"overdue": true,
"decidedAt": "2026-08-10T09:00:00Z",
"notes": "string",
"requiredByWorkspace": true,
"detail": "string"
},
"media": {},
"createdAt": "2026-08-10T09:00:00Z",
"updatedAt": "2026-08-10T09:00:00Z"
}
}