Posts

Update post draft

Updates a draft's title, content (saved as a new version), and/or assigned profile. Fails on scheduled/published posts.

PATCH/api/public/posts/:id
cURLPATCH /api/public/posts/:id
curl -X PATCH https://postiv.ai/api/public/posts/ID_ID \
  -H "Authorization: Bearer pk_postiv_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Launch lessons",
    "content": "Three things we learned from launch week..."
  }'
200Response
{
  "success": true,
  "post": {
    "id": "post1...",
    "status": "draft",
    "content": "Updated text..."
  },
  "version": {
    "id": "v2...",
    "versionNumber": 2,
    "createdAt": "2026-07-19T09:05:00.000Z"
  }
}

Authorization

Requires an organization API key with the posts:write scope, sent as Authorization: Bearer or x-api-key.

Path parameters

idstringrequired

Resource id from the corresponding list or create endpoint.

Body parameters

titlestring|null

Max 240 chars; null clears it.

contentstring

Max 100000 chars; stored as a new post_versions row.

integrationIdint|null

Alias: integration_id. null unassigns.

Response

The updated post plus the new version (if content changed).

postobject

Full post object, same shape as GET.

versionobject|null

{ id, versionNumber, createdAt }; null if content wasn't provided or was unchanged (no-op save).

Errors

400validation_error: none of title/content/integrationId provided
404post_not_found
409post_scheduled_locked: post is scheduled; unschedule first
409post_published_immutable: post already published
409content_plan_profile_locked: post is linked to a Bob plan item and the requested integrationId doesn't match that plan's profile
404linkedin_profile_not_found: new integrationId not in this workspace

Good to know

  • A no-change content save (identical to the current version) is silently skipped: version returns null rather than creating a duplicate version row.