Skip to content

Commit 6dfb364

Browse files
tessclaude
andcommitted
docs(GEN-6844): editing a post that is already live
Closes GEN-6844. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 6ca85db commit 6dfb364

4 files changed

Lines changed: 279 additions & 2 deletions

File tree

‎public/llms-full.txt‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,26 @@ PATCH /v1/schedule/post/{post_id} // same content fields as create + schedule
10911091
DELETE /v1/schedule/post/{post_id}
10921092
```
10931093

1094+
### Edit a post that is already live
1095+
1096+
```
1097+
PATCH /v1/schedule/post/{post_id}/published
1098+
{ "description": "Corrected sourcing figures in the pinned comment." }
1099+
→ { "post_id": 48213,
1100+
"results": [ { "platform": "youtube", "platform_post_id": "dQw4w9WgXcQ", "result": "updated",
1101+
"updated_fields": ["description"], "quota_units": 50,
1102+
"metadata": { "title": "Factory price reveal", "description": "Corrected sourcing figures...",
1103+
"tags": ["sourcing","beauty"], "category_id": 22 } } ] }
1104+
```
1105+
1106+
Editable fields per platform come from `editable_after_publish` in `GET /v1/schedule/platforms`. Today: **YouTube** `title` (≤100, not blank), `description` (≤5,000 **bytes**, not characters; explicit `null` clears it), `tags` (each 2+ chars, ≤400 chars total), `category_id` (positive int). Every other platform is `[]` — TikTok, Instagram and Facebook have no post-publication edit for this content, editing a sent tweet is a paid X plan feature, and LinkedIn's `commentary` PARTIAL_UPDATE is not wired yet.
1107+
1108+
**Sparse and idempotent.** Only the fields in the body change. GEN reads the platform's current metadata, merges the change onto it and writes it back, so an unsent title is never cleared and the same request twice converges rather than stacking. `metadata` is read back *from the platform* after the write, not echoed from the request.
1109+
1110+
`result` per platform: `updated` · `unsupported_after_publish` (that network has no edit path; nothing was touched — not an auth error) · `reauthorization_required` (GEN's saved authorization can no longer edit it; reconnect via GEN app → Setup → Accounts) · `failed` (`message` carries the platform's reason, e.g. `quotaExceeded`).
1111+
1112+
`422`: `post_not_published` (it has not gone out — use `PATCH /v1/schedule/post/{post_id}`), an empty body, or `platform_validation_failed` naming the `field` (a field the platform cannot change after publishing, or one over its limit). Each YouTube update costs 50 units of the connected channel's YouTube API quota.
1113+
10941114
### Upload media (upload_asset)
10951115

10961116
Posts reference media by URL (public at post time; a render URL works directly). Upload a local file to get a hosted URL, also saved to the agent's Assets.

‎public/llms.txt‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,15 @@ curl "https://api.gen.pro/v1/schedule/post/48213" -H "X-API-Key: $GEN_API_KEY"
551551
# published: platform_post_id + post_url (the live link). failed: error, error_code, failed_step.
552552
```
553553

554+
**Already live and wrong?** `PATCH /v1/schedule/post/:post_id/published` edits a published post's metadata where the network supports it — today YouTube `title`, `description`, `tags`, `category_id`. Sparse: only the fields you send change, everything else on the live post is preserved, and the same request twice converges instead of stacking. The reply is one result per platform — `updated` (with the platform's readback), `unsupported_after_publish` (that network has no edit path; nothing touched), `reauthorization_required` (reconnect the account) or `failed`. `editable_after_publish` in `GET /v1/schedule/platforms` names the editable fields per platform. Each YouTube update costs 50 units of the channel's YouTube quota. For a post that has *not* gone out yet, use `PATCH /v1/schedule/post/:post_id` instead.
555+
556+
```bash
557+
curl -X PATCH "https://api.gen.pro/v1/schedule/post/48213/published" -H "X-API-Key: $GEN_API_KEY" \
558+
-H "Content-Type: application/json" -d '{"description": "Corrected sourcing figures in the pinned comment."}'
559+
# { "post_id": 48213, "results": [ { "platform": "youtube", "result": "updated",
560+
# "updated_fields": ["description"], "metadata": {...}, "quota_units": 50 } ] }
561+
```
562+
554563
**Limits that bite:** X 280 chars/tweet + max 4 images; YouTube title required (≤100), description ≤5,000, `thumbnail_url` https .jpg/.png <2 MB; TikTok/Instagram 2,200 (Instagram ≤30 hashtags, 2-10 items = carousel); LinkedIn 3,000, ≤9 images or one PDF/PPTX/DOCX document, no mixing; Facebook video only. Instagram/TikTok/Facebook/YouTube need media; X and LinkedIn allow text-only. Per-platform knobs: `instagram_music`, `youtube_options` (visibility, shorts, tags), `linkedin_options` (visibility, alt_text, carousel = PDF of the images; several images alone render as a grid). A 422 `platform_validation_failed` names the `platform` and `field` (dotted for options). `GET /v1/schedule/platforms` (no auth) serves the rules incl. each `options` object.
555564

556565
**Prerequisites for publish.** The agent must have connected the platform (GEN app → Setup → Accounts, or MCP `gen_get_social_connect_url`). Media URLs must be publicly accessible at post time.
@@ -564,7 +573,8 @@ GET /v1/schedule/platforms — per-plat
564573
POST /v1/schedule/with-post — publish now / schedule (all platforms)
565574
GET /v1/schedule/post/:post_id — outcome per platform + post_url
566575
GET /v1/schedule/posts?agent_id=&start_date=&end_date= — content calendar
567-
PATCH /v1/schedule/post/:post_id · DELETE /v1/schedule/post/:post_id
576+
PATCH /v1/schedule/post/:post_id · DELETE /v1/schedule/post/:post_id — before it goes out
577+
PATCH /v1/schedule/post/:post_id/published — edit a LIVE post's metadata (YouTube)
568578
POST /v1/social/upload_asset — upload a local file → hosted URL
569579
```
570580

‎public/openapi.yaml‎

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,111 @@ paths:
21782178
'404':
21792179
$ref: '#/components/responses/NotFound'
21802180

2181+
/schedule/post/{post_id}/published:
2182+
parameters:
2183+
- name: post_id
2184+
in: path
2185+
required: true
2186+
description: The `post_id` of a post that has already published.
2187+
schema:
2188+
type: integer
2189+
patch:
2190+
operationId: updatePublishedPost
2191+
x-phase: [export]
2192+
summary: Edit the metadata of a post that is already live
2193+
description: |
2194+
Change a published post's metadata where the destination network supports it — today, a YouTube video's `title`, `description`, `tags` and `category_id`. `GET /schedule/platforms` names the editable fields per platform in `editable_after_publish`.
2195+
2196+
The edit is **sparse**: only the fields in the request body change. GEN reads the platform's current metadata, merges your change onto it, writes it back, and returns what the platform held afterwards — so a title you did not send is not cleared, and the same request sent twice converges on the same result rather than stacking edits.
2197+
2198+
The response is `200` with one result per platform the post went out on, each `updated`, `unsupported_after_publish`, `reauthorization_required` or `failed`. A network with no edit path is reported as `unsupported_after_publish` and nothing is touched; it is never an authentication error. A `422` means the body itself is wrong — a field the platform cannot change after publishing, or one that breaks the platform's limits.
2199+
2200+
Use `PATCH /schedule/post/{post_id}` for a post that has **not** gone out yet; that endpoint still refuses published posts.
2201+
2202+
Each YouTube update consumes 50 units of the connected channel's YouTube API quota.
2203+
tags: [Publishing]
2204+
requestBody:
2205+
required: true
2206+
content:
2207+
application/json:
2208+
schema:
2209+
$ref: '#/components/schemas/PublishedPostUpdate'
2210+
examples:
2211+
fixDescription:
2212+
summary: Fix a typo in a live YouTube description
2213+
value:
2214+
description: "What your $12 beauty sponge really costs — corrected sourcing figures in the pinned comment."
2215+
retitleAndRetag:
2216+
summary: Retitle, retag and recategorise
2217+
value:
2218+
title: "Factory price reveal (2026 update)"
2219+
tags: [sourcing, beauty, supply chain]
2220+
category_id: 24
2221+
responses:
2222+
'200':
2223+
description: One result per platform the post published to.
2224+
content:
2225+
application/json:
2226+
schema:
2227+
$ref: '#/components/schemas/PublishedPostUpdateResponse'
2228+
examples:
2229+
updated:
2230+
summary: YouTube accepted the edit
2231+
value:
2232+
post_id: 120750
2233+
results:
2234+
- platform: youtube
2235+
platform_post_id: "dQw4w9WgXcQ"
2236+
result: updated
2237+
updated_fields: [description]
2238+
metadata:
2239+
title: "Factory price reveal"
2240+
description: "What your $12 beauty sponge really costs — corrected sourcing figures in the pinned comment."
2241+
tags: [sourcing, beauty]
2242+
category_id: 22
2243+
quota_units: 50
2244+
unsupported:
2245+
summary: The platform has no post-publication edit
2246+
value:
2247+
post_id: 120751
2248+
results:
2249+
- platform: tiktok
2250+
platform_post_id: "7412..."
2251+
result: unsupported_after_publish
2252+
message: "tiktok has no supported post-publication edit for this content."
2253+
reauthorization:
2254+
summary: The connected account must be reconnected
2255+
value:
2256+
post_id: 120750
2257+
results:
2258+
- platform: youtube
2259+
platform_post_id: "dQw4w9WgXcQ"
2260+
result: reauthorization_required
2261+
message: "Reconnect the YouTube account: GEN's saved authorization is no longer usable."
2262+
'401':
2263+
$ref: '#/components/responses/Unauthorized'
2264+
'403':
2265+
description: You do not have permission to edit this post.
2266+
'404':
2267+
$ref: '#/components/responses/NotFound'
2268+
'422':
2269+
description: |
2270+
The post has not published yet (`post_not_published`), the body is empty, or a field is not editable after publishing / breaks the platform's limits (`platform_validation_failed`).
2271+
content:
2272+
application/json:
2273+
schema:
2274+
$ref: '#/components/schemas/PlatformValidationError'
2275+
example:
2276+
detail:
2277+
error: "YouTube cannot change visibility after publishing"
2278+
error_code: platform_validation_failed
2279+
platform: youtube
2280+
field: visibility
2281+
errors:
2282+
- platform: youtube
2283+
field: visibility
2284+
error: "YouTube cannot change visibility after publishing"
2285+
21812286
/templates/projects:
21822287
get:
21832288
operationId: listTemplates
@@ -5430,9 +5535,82 @@ components:
54305535
linkedin_options:
54315536
visibility: "public (default) | connections | loggedin"
54325537
alt_text: "string[] — alternative text per image, in media order (images only)"
5538+
editable_after_publish:
5539+
type: array
5540+
description: |
5541+
Fields `PATCH /schedule/post/{post_id}/published` can still change once the post is live. Empty means the network has no supported post-publication edit and that endpoint answers `unsupported_after_publish` for it.
5542+
items:
5543+
type: string
5544+
example: [title, description, tags, category_id]
54335545
notes:
54345546
type: string
54355547

5548+
PublishedPostUpdate:
5549+
type: object
5550+
description: |
5551+
A sparse metadata edit for a post that has already published. Send only the fields you want changed; every other field on the live post is preserved. At least one field is required.
5552+
minProperties: 1
5553+
properties:
5554+
title:
5555+
type: string
5556+
description: New title. YouTube allows up to 100 characters and rejects a blank title.
5557+
description:
5558+
type: string
5559+
description: |
5560+
New description / caption. YouTube allows up to 5,000 **bytes** (not characters — emoji and CJK cost several bytes each). An explicit `null` clears the description.
5561+
tags:
5562+
type: array
5563+
description: YouTube only — replaces the video's tags. Each tag is 2+ characters and all tags together are at most 400 characters.
5564+
items:
5565+
type: string
5566+
category_id:
5567+
type: integer
5568+
description: YouTube only — video category ID (for example 22 People & Blogs, 24 Entertainment).
5569+
5570+
PublishedPostUpdateResult:
5571+
type: object
5572+
properties:
5573+
platform:
5574+
$ref: '#/components/schemas/PublishPlatform'
5575+
platform_post_id:
5576+
type: string
5577+
nullable: true
5578+
description: The platform's own ID for the live post (a YouTube video ID).
5579+
result:
5580+
type: string
5581+
enum: [updated, unsupported_after_publish, reauthorization_required, failed]
5582+
description: |
5583+
`updated` — the platform accepted the edit and `metadata` is what it holds now.
5584+
`unsupported_after_publish` — this network has no post-publication edit for this content; nothing was touched.
5585+
`reauthorization_required` — GEN's saved authorization for this account can no longer edit the post; the user must reconnect it (GEN app → Setup → Accounts).
5586+
`failed` — the platform rejected the edit; `message` carries its reason.
5587+
updated_fields:
5588+
type: array
5589+
description: Present on `updated` — the fields that were sent to the platform.
5590+
items:
5591+
type: string
5592+
metadata:
5593+
type: object
5594+
description: Present on `updated` — the metadata read back from the platform after the write, not the values that were sent.
5595+
quota_units:
5596+
type: integer
5597+
description: Present on `updated` — the platform API quota the update consumed (YouTube charges 50 units per update).
5598+
example: 50
5599+
message:
5600+
type: string
5601+
description: Why this platform could not be updated. Absent on `updated`.
5602+
5603+
PublishedPostUpdateResponse:
5604+
type: object
5605+
properties:
5606+
post_id:
5607+
type: integer
5608+
results:
5609+
type: array
5610+
description: One entry per platform the post went out on, in the post's platform order.
5611+
items:
5612+
$ref: '#/components/schemas/PublishedPostUpdateResult'
5613+
54365614
InstagramMusic:
54375615
type: object
54385616
description: Instagram only. Mixes a music track under every video item before upload (Instagram cannot attach audio to images or carousels via API). Needs at least one video item.

0 commit comments

Comments
 (0)