Skip to main content
PUT
/
api
/
calendar
/
posts
Update a scheduled social post (bulk endpoint)
curl --request PUT \
  --url https://app.puffle.ai/api/calendar/posts \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "content": "<string>",
  "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "title": "<string>",
  "hashtags": [
    "<string>"
  ],
  "channels": [
    "<string>"
  ],
  "scheduled_at": "2023-11-07T05:31:56Z",
  "account_ids": [
    "3c90c3cc-0d44-4b50-8888-8dd25736052a"
  ],
  "status": "draft",
  "media_items": [
    {
      "url": "<string>",
      "type": "image"
    }
  ]
}
'
{
  "post": {
    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "calendar_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "title": "<string>",
    "content": "<string>",
    "hashtags": [
      "<string>"
    ],
    "channels": [
      "<string>"
    ],
    "scheduled_at": "2023-11-07T05:31:56Z",
    "account_ids": [
      "3c90c3cc-0d44-4b50-8888-8dd25736052a"
    ],
    "status": "draft",
    "late_post_id": "<string>",
    "media_items": [
      {
        "url": "<string>",
        "type": "image"
      }
    ],
    "archived_at": "2023-11-07T05:31:56Z",
    "account_profile_picture": "<string>",
    "account_display_name": "<string>"
  }
}

Overview

Update a single post by id in the request body. The handler mirrors changes into Late: creates, updates, or deletes the Late post depending on whether account_ids and content remain valid. If account_ids changes, the old Late post is deleted and a fresh one is created (Late binds posts to specific account profiles). Despite the legacy bulk wrapper name in the routing code, this endpoint updates exactly one post per call. Prefer updateSocialPost (PUT /api/calendar/posts/{postId}) for new integrations — this body-ID form is kept for legacy clients.

AI agent notes

Fields replace, not merge. media_items: [] clears attachments; hashtags: [] clears hashtags. Omitted fields are coerced to default empties, not left untouched.Validation:
  • content must be non-empty
  • Scheduling into the past is blocked
Account swaps trigger a Late recreation. If the new account_ids set is empty and content is empty, the Late post is deleted entirely and late_post_id is cleared locally.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json

All fields are replaced (not partial-merged). Re-send media_items: [] to clear attachments; omitting it is also treated as []. When accounts change, the server deletes and recreates the Late post since Late binds posts to specific account profiles.

content
string
required

Post body text. Required and non-empty.

Minimum string length: 1
id
string<uuid>
required

Post ID to update.

Pattern: ^([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)$
title
string | null
hashtags
string[]

Hashtags without the leading #. Appended to content before sending to Late since LinkedIn has no separate hashtag field.

channels
string[]

Legacy channel list, e.g. ['linkedin']. Fallback targeting when account_ids is empty.

scheduled_at
string<date-time> | null

ISO timestamp. Required when status === 'scheduled'. Must be in the future (1-minute grace window).

Pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
account_ids
string<uuid>[]

Target social account IDs. If empty and channels includes linkedin, the server falls back to the caller's first LinkedIn account.

Pattern: ^([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)$
status
enum<string>

Defaults to draft. scheduled queues with Late; posted is for importing already-published posts from onboarding.

Available options:
draft,
scheduled,
posted
media_items
object[]

Optional media attachments. Each URL must come from uploadSocialMedia.

Response

Post updated.

post
object
required

Canonical social post row.