Meet the new Scripe, live on October 7.Register

OpenAPI reference · Posts

Update a post (content, status, schedule)

PATCH/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 /me ping + token refresh for personal brands (non-empty admin set for company pages). If LinkedIn isn't usable the request fails 409 conflict with details.reason / details.reconnectUrl / details.retryable: false, and the post is left unchanged.
  • null unschedules 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

  • Authorizationstringrequired

    Bearer token in the Authorization header.

    Pass Authorization: Bearer scripe_sk_live_<...> (or scripe_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 except webhooks:manage, which is grantable to OAuth tokens only today — the webhook-endpoint operations answer 403 scope_missing to every API key. Operations that name no scope accept any valid token of the workspace.

Path parameters

  • postIdstringrequired

Header parameters

  • Scripe-Api-Versionstring

    Pin the API version. Format YYYY-MM-DD. Omit to receive the currently rolling default. Unknown versions return 400 version_unsupported.

  • Idempotency-Keystring

    Opaque 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 returns 409 idempotency_key_conflict.

    Strongly recommended for every write — see /docs/api/v1/idempotency.

Request bodyapplication/json

  • contentstring
  • titlestring

    The 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 the content you 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.

  • contentTypestring

    Allowed values: PERSONAL, BUSINESS_INTERNAL, BUSINESS_EXTERNAL, EDUCATIONAL, UNKNOWN

  • statusCategorystring

    Move the post to the workspace's default status in this lifecycle category. Mutually exclusive with statusId.

    Allowed values: suggested, draft, inProgress, review, scheduled, published

  • statusIdstring

    Move the post to a specific custom status by id (from GET /post-statuses). Mutually exclusive with statusCategory.

  • scheduledForstring <date-time> | null

    Future ISO timestamp to schedule/reschedule the post (LinkedIn connection verified first). null unschedules. Omit to leave unchanged.

    Offset-less timestamps resolve in the project's calendar timezone; a bare date is rejected. See PostCreate.scheduledFor.

  • autoLikeboolean

    Enable auto-like engagement when the post goes live.

  • autoCommentboolean

    Enable 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-Key conflict, 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

bash
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)

json
{
  "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"
  }
}