Save a draft
curl --request POST \
--url https://posted-api.example.com/api/drafts/{draftId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "An unfinished studio update.",
"connectionIds": [
"11111111-1111-4111-8111-111111111111"
],
"mediaIds": [
"44444444-4444-4444-8444-444444444444"
],
"textOverrides": {},
"version": 0,
"idempotencyKey": "studio-draft-2027-01-18"
}
'import requests
url = "https://posted-api.example.com/api/drafts/{draftId}"
payload = {
"text": "An unfinished studio update.",
"connectionIds": ["11111111-1111-4111-8111-111111111111"],
"mediaIds": ["44444444-4444-4444-8444-444444444444"],
"textOverrides": {},
"version": 0,
"idempotencyKey": "studio-draft-2027-01-18"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
text: 'An unfinished studio update.',
connectionIds: ['11111111-1111-4111-8111-111111111111'],
mediaIds: ['44444444-4444-4444-8444-444444444444'],
textOverrides: {},
version: 0,
idempotencyKey: 'studio-draft-2027-01-18'
})
};
fetch('https://posted-api.example.com/api/drafts/{draftId}', 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://posted-api.example.com/api/drafts/{draftId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'An unfinished studio update.',
'connectionIds' => [
'11111111-1111-4111-8111-111111111111'
],
'mediaIds' => [
'44444444-4444-4444-8444-444444444444'
],
'textOverrides' => [
],
'version' => 0,
'idempotencyKey' => 'studio-draft-2027-01-18'
]),
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://posted-api.example.com/api/drafts/{draftId}"
payload := strings.NewReader("{\n \"text\": \"An unfinished studio update.\",\n \"connectionIds\": [\n \"11111111-1111-4111-8111-111111111111\"\n ],\n \"mediaIds\": [\n \"44444444-4444-4444-8444-444444444444\"\n ],\n \"textOverrides\": {},\n \"version\": 0,\n \"idempotencyKey\": \"studio-draft-2027-01-18\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://posted-api.example.com/api/drafts/{draftId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"An unfinished studio update.\",\n \"connectionIds\": [\n \"11111111-1111-4111-8111-111111111111\"\n ],\n \"mediaIds\": [\n \"44444444-4444-4444-8444-444444444444\"\n ],\n \"textOverrides\": {},\n \"version\": 0,\n \"idempotencyKey\": \"studio-draft-2027-01-18\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://posted-api.example.com/api/drafts/{draftId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"An unfinished studio update.\",\n \"connectionIds\": [\n \"11111111-1111-4111-8111-111111111111\"\n ],\n \"mediaIds\": [\n \"44444444-4444-4444-8444-444444444444\"\n ],\n \"textOverrides\": {},\n \"version\": 0,\n \"idempotencyKey\": \"studio-draft-2027-01-18\"\n}"
response = http.request(request)
puts response.read_body{
"draft": {
"id": "33333333-3333-4333-8333-333333333333",
"text": "An unfinished studio update.",
"additionalPosts": [],
"mediaOverrides": {},
"textOverrides": {},
"connectionIds": [
"11111111-1111-4111-8111-111111111111"
],
"connections": [
{
"id": "11111111-1111-4111-8111-111111111111",
"provider": "bluesky",
"accountId": "did:plc:example",
"name": "Alex Morgan",
"handle": "alex.example.test",
"avatarUrl": null,
"state": "connected",
"createdAt": "2027-01-18T09:30:00.000Z"
}
],
"media": [
{
"id": "44444444-4444-4444-8444-444444444444",
"fileName": "studio.jpg",
"contentType": "image/jpeg",
"sizeBytes": 245760,
"width": 1600,
"height": 900,
"alt": "A bright studio desk beside a window",
"durationSeconds": null
}
],
"version": 1,
"createdAt": "2027-01-18T09:30:00.000Z",
"updatedAt": "2027-01-18T09:30:00.000Z",
"draftedBy": {
"id": "66666666-6666-4666-8666-666666666666",
"name": "Alex Morgan",
"avatarUrl": null
}
}
}{
"draft": {
"id": "33333333-3333-4333-8333-333333333333",
"text": "An unfinished studio update.",
"additionalPosts": [],
"mediaOverrides": {},
"textOverrides": {},
"connectionIds": [
"11111111-1111-4111-8111-111111111111"
],
"connections": [
{
"id": "11111111-1111-4111-8111-111111111111",
"provider": "bluesky",
"accountId": "did:plc:example",
"name": "Alex Morgan",
"handle": "alex.example.test",
"avatarUrl": null,
"state": "connected",
"createdAt": "2027-01-18T09:30:00.000Z"
}
],
"media": [
{
"id": "44444444-4444-4444-8444-444444444444",
"fileName": "studio.jpg",
"contentType": "image/jpeg",
"sizeBytes": 245760,
"width": 1600,
"height": 900,
"alt": "A bright studio desk beside a window",
"durationSeconds": null
}
],
"version": 1,
"createdAt": "2027-01-18T09:30:00.000Z",
"updatedAt": "2027-01-18T09:30:00.000Z",
"draftedBy": {
"id": "66666666-6666-4666-8666-666666666666",
"name": "Alex Morgan",
"avatarUrl": null
}
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>"
}
}Save a draft
Save incomplete content without publishing. Use version 0 and a new draftId for a new draft, or its current version to update. Reuse the request key for retries.
POST
/
api
/
drafts
/
{draftId}
Save a draft
curl --request POST \
--url https://posted-api.example.com/api/drafts/{draftId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "An unfinished studio update.",
"connectionIds": [
"11111111-1111-4111-8111-111111111111"
],
"mediaIds": [
"44444444-4444-4444-8444-444444444444"
],
"textOverrides": {},
"version": 0,
"idempotencyKey": "studio-draft-2027-01-18"
}
'import requests
url = "https://posted-api.example.com/api/drafts/{draftId}"
payload = {
"text": "An unfinished studio update.",
"connectionIds": ["11111111-1111-4111-8111-111111111111"],
"mediaIds": ["44444444-4444-4444-8444-444444444444"],
"textOverrides": {},
"version": 0,
"idempotencyKey": "studio-draft-2027-01-18"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
text: 'An unfinished studio update.',
connectionIds: ['11111111-1111-4111-8111-111111111111'],
mediaIds: ['44444444-4444-4444-8444-444444444444'],
textOverrides: {},
version: 0,
idempotencyKey: 'studio-draft-2027-01-18'
})
};
fetch('https://posted-api.example.com/api/drafts/{draftId}', 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://posted-api.example.com/api/drafts/{draftId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'An unfinished studio update.',
'connectionIds' => [
'11111111-1111-4111-8111-111111111111'
],
'mediaIds' => [
'44444444-4444-4444-8444-444444444444'
],
'textOverrides' => [
],
'version' => 0,
'idempotencyKey' => 'studio-draft-2027-01-18'
]),
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://posted-api.example.com/api/drafts/{draftId}"
payload := strings.NewReader("{\n \"text\": \"An unfinished studio update.\",\n \"connectionIds\": [\n \"11111111-1111-4111-8111-111111111111\"\n ],\n \"mediaIds\": [\n \"44444444-4444-4444-8444-444444444444\"\n ],\n \"textOverrides\": {},\n \"version\": 0,\n \"idempotencyKey\": \"studio-draft-2027-01-18\"\n}")
req, _ := http.NewRequest("POST", 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.post("https://posted-api.example.com/api/drafts/{draftId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"An unfinished studio update.\",\n \"connectionIds\": [\n \"11111111-1111-4111-8111-111111111111\"\n ],\n \"mediaIds\": [\n \"44444444-4444-4444-8444-444444444444\"\n ],\n \"textOverrides\": {},\n \"version\": 0,\n \"idempotencyKey\": \"studio-draft-2027-01-18\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://posted-api.example.com/api/drafts/{draftId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"An unfinished studio update.\",\n \"connectionIds\": [\n \"11111111-1111-4111-8111-111111111111\"\n ],\n \"mediaIds\": [\n \"44444444-4444-4444-8444-444444444444\"\n ],\n \"textOverrides\": {},\n \"version\": 0,\n \"idempotencyKey\": \"studio-draft-2027-01-18\"\n}"
response = http.request(request)
puts response.read_body{
"draft": {
"id": "33333333-3333-4333-8333-333333333333",
"text": "An unfinished studio update.",
"additionalPosts": [],
"mediaOverrides": {},
"textOverrides": {},
"connectionIds": [
"11111111-1111-4111-8111-111111111111"
],
"connections": [
{
"id": "11111111-1111-4111-8111-111111111111",
"provider": "bluesky",
"accountId": "did:plc:example",
"name": "Alex Morgan",
"handle": "alex.example.test",
"avatarUrl": null,
"state": "connected",
"createdAt": "2027-01-18T09:30:00.000Z"
}
],
"media": [
{
"id": "44444444-4444-4444-8444-444444444444",
"fileName": "studio.jpg",
"contentType": "image/jpeg",
"sizeBytes": 245760,
"width": 1600,
"height": 900,
"alt": "A bright studio desk beside a window",
"durationSeconds": null
}
],
"version": 1,
"createdAt": "2027-01-18T09:30:00.000Z",
"updatedAt": "2027-01-18T09:30:00.000Z",
"draftedBy": {
"id": "66666666-6666-4666-8666-666666666666",
"name": "Alex Morgan",
"avatarUrl": null
}
}
}{
"draft": {
"id": "33333333-3333-4333-8333-333333333333",
"text": "An unfinished studio update.",
"additionalPosts": [],
"mediaOverrides": {},
"textOverrides": {},
"connectionIds": [
"11111111-1111-4111-8111-111111111111"
],
"connections": [
{
"id": "11111111-1111-4111-8111-111111111111",
"provider": "bluesky",
"accountId": "did:plc:example",
"name": "Alex Morgan",
"handle": "alex.example.test",
"avatarUrl": null,
"state": "connected",
"createdAt": "2027-01-18T09:30:00.000Z"
}
],
"media": [
{
"id": "44444444-4444-4444-8444-444444444444",
"fileName": "studio.jpg",
"contentType": "image/jpeg",
"sizeBytes": 245760,
"width": 1600,
"height": 900,
"alt": "A bright studio desk beside a window",
"durationSeconds": null
}
],
"version": 1,
"createdAt": "2027-01-18T09:30:00.000Z",
"updatedAt": "2027-01-18T09:30:00.000Z",
"draftedBy": {
"id": "66666666-6666-4666-8666-666666666666",
"name": "Alex Morgan",
"avatarUrl": null
}
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>"
}
}Write access: a member/administrator with a write-enabled credential, or an authorized signed-in user.
Save incomplete content without publishing. Use version 0 and a new draftId for a new draft, or its current version to update. Reuse the request key for retries.
Use version 0 for a new UUID, or the latest version for an update. Reuse the same idempotencyKey and identical content when retrying. Incomplete content is allowed. Saving does not publish.
MCP clients can use
save_draft for this operation.
Request conventions · API keys · MCP connectionsAuthorizations
bearerAuthsessionCookie
Personal or team Posted REST API key
Path Parameters
The draftId from the corresponding list, record or authorization response.
Body
application/json
Maximum string length:
64000Maximum array length:
50Pattern:
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$Maximum array length:
20Pattern:
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$Required range:
0 <= x <= 9007199254740991Pattern:
^[A-Za-z0-9._:-]{8,128}$Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Response
Existing operation replay or saved-draft update.
Show child attributes
Show child attributes
Was this page helpful?
