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>",
"statusId": "<string>",
"scheduledFor": "2026-08-18T09:00:00+02:00",
"autoLike": true,
"autoComment": true
}
'import requests
url = "https://api.scripe.io/v1/posts/{postId}"
payload = {
"content": "<string>",
"title": "<string>",
"statusId": "<string>",
"scheduledFor": "2026-08-18T09:00:00+02:00",
"autoLike": True,
"autoComment": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
content: '<string>',
title: '<string>',
statusId: '<string>',
scheduledFor: '2026-08-18T09:00:00+02:00',
autoLike: true,
autoComment: true
})
};
fetch('https://api.scripe.io/v1/posts/{postId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scripe.io/v1/posts/{postId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'content' => '<string>',
'title' => '<string>',
'statusId' => '<string>',
'scheduledFor' => '2026-08-18T09:00:00+02:00',
'autoLike' => true,
'autoComment' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scripe.io/v1/posts/{postId}"
payload := strings.NewReader("{\n \"content\": \"<string>\",\n \"title\": \"<string>\",\n \"statusId\": \"<string>\",\n \"scheduledFor\": \"2026-08-18T09:00:00+02:00\",\n \"autoLike\": true,\n \"autoComment\": true\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.scripe.io/v1/posts/{postId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"content\": \"<string>\",\n \"title\": \"<string>\",\n \"statusId\": \"<string>\",\n \"scheduledFor\": \"2026-08-18T09:00:00+02:00\",\n \"autoLike\": true,\n \"autoComment\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scripe.io/v1/posts/{postId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"content\": \"<string>\",\n \"title\": \"<string>\",\n \"statusId\": \"<string>\",\n \"scheduledFor\": \"2026-08-18T09:00:00+02:00\",\n \"autoLike\": true,\n \"autoComment\": true\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "post_a1b2c3d4e5f6g7h8",
"status": "waitingProcessing",
"statusCategory": "suggested",
"platform": "<string>",
"contentType": "<string>",
"title": "<string>",
"content": "<string>",
"contentTruncated": true,
"publishedAt": "2023-11-07T05:31:56Z",
"delivery": {
"state": "not_scheduled",
"willRetry": true,
"retryUntil": "2023-11-07T05:31:56Z",
"detail": "<string>"
},
"review": {
"state": "not_requested",
"awaitingDecision": true,
"reviewerUserId": "<string>",
"deadline": "2023-11-07T05:31:56Z",
"overdue": true,
"decidedAt": "2023-11-07T05:31:56Z",
"notes": "<string>",
"requiredByWorkspace": true,
"detail": "<string>"
},
"media": {
"kind": "images",
"images": [
{
"key": "rrb7bw8pfuc.png",
"alt": "<string>",
"name": "<string>"
}
]
},
"createdAt": "2023-11-07T05:31:56Z",
"projectId": "<string>",
"statusId": "<string>",
"statusTitle": "<string>",
"funnelStage": "REACH",
"scheduledAt": "2023-11-07T05:31:56Z",
"lastPublishError": "<string>",
"lastPublishAttemptAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}Update a post (content, status, schedule)
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.
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>",
"statusId": "<string>",
"scheduledFor": "2026-08-18T09:00:00+02:00",
"autoLike": true,
"autoComment": true
}
'import requests
url = "https://api.scripe.io/v1/posts/{postId}"
payload = {
"content": "<string>",
"title": "<string>",
"statusId": "<string>",
"scheduledFor": "2026-08-18T09:00:00+02:00",
"autoLike": True,
"autoComment": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
content: '<string>',
title: '<string>',
statusId: '<string>',
scheduledFor: '2026-08-18T09:00:00+02:00',
autoLike: true,
autoComment: true
})
};
fetch('https://api.scripe.io/v1/posts/{postId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.scripe.io/v1/posts/{postId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'content' => '<string>',
'title' => '<string>',
'statusId' => '<string>',
'scheduledFor' => '2026-08-18T09:00:00+02:00',
'autoLike' => true,
'autoComment' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.scripe.io/v1/posts/{postId}"
payload := strings.NewReader("{\n \"content\": \"<string>\",\n \"title\": \"<string>\",\n \"statusId\": \"<string>\",\n \"scheduledFor\": \"2026-08-18T09:00:00+02:00\",\n \"autoLike\": true,\n \"autoComment\": true\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.scripe.io/v1/posts/{postId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"content\": \"<string>\",\n \"title\": \"<string>\",\n \"statusId\": \"<string>\",\n \"scheduledFor\": \"2026-08-18T09:00:00+02:00\",\n \"autoLike\": true,\n \"autoComment\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scripe.io/v1/posts/{postId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"content\": \"<string>\",\n \"title\": \"<string>\",\n \"statusId\": \"<string>\",\n \"scheduledFor\": \"2026-08-18T09:00:00+02:00\",\n \"autoLike\": true,\n \"autoComment\": true\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "post_a1b2c3d4e5f6g7h8",
"status": "waitingProcessing",
"statusCategory": "suggested",
"platform": "<string>",
"contentType": "<string>",
"title": "<string>",
"content": "<string>",
"contentTruncated": true,
"publishedAt": "2023-11-07T05:31:56Z",
"delivery": {
"state": "not_scheduled",
"willRetry": true,
"retryUntil": "2023-11-07T05:31:56Z",
"detail": "<string>"
},
"review": {
"state": "not_requested",
"awaitingDecision": true,
"reviewerUserId": "<string>",
"deadline": "2023-11-07T05:31:56Z",
"overdue": true,
"decidedAt": "2023-11-07T05:31:56Z",
"notes": "<string>",
"requiredByWorkspace": true,
"detail": "<string>"
},
"media": {
"kind": "images",
"images": [
{
"key": "rrb7bw8pfuc.png",
"alt": "<string>",
"name": "<string>"
}
]
},
"createdAt": "2023-11-07T05:31:56Z",
"projectId": "<string>",
"statusId": "<string>",
"statusTitle": "<string>",
"funnelStage": "REACH",
"scheduledAt": "2023-11-07T05:31:56Z",
"lastPublishError": "<string>",
"lastPublishAttemptAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}{
"error": {
"code": "not_found",
"message": "<string>",
"request_id": "req_a1b2c3d4e5f6",
"docs_url": "<string>",
"details": "<unknown>"
}
}Authorizations
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.
Headers
Pin the API version. Format YYYY-MM-DD. Omit to receive the
currently rolling default. Unknown versions return 400 version_unsupported.
"2026-08-10"
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 returns409 idempotency_key_conflict.
Strongly recommended for every write — see
/docs/api/v1/idempotency.
^[A-Za-z0-9_-]{1,64}$Path Parameters
"post_a1b2c3d4e5f6g7h8"
Body
Partial update. All fields optional. statusCategory and
statusId are mutually exclusive. scheduledFor accepts a
future timestamp (schedule/reschedule), null (unschedule), or
may be omitted (leave schedule unchanged).
100000The 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.
500PERSONAL, BUSINESS_INTERNAL, BUSINESS_EXTERNAL, EDUCATIONAL, UNKNOWN Move the post to the workspace's default status in this
lifecycle category. Mutually exclusive with statusId.
suggested, draft, inProgress, review, scheduled, published Move the post to a specific custom status by id (from
GET /post-statuses). Mutually exclusive with
statusCategory.
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.
"2026-08-18T09:00:00+02:00"
Enable auto-like engagement when the post goes live.
Enable auto-comment engagement when the post goes live.
Response
Post updated.
Show child attributes
Show child attributes