Skip to main content
Glama

Bulk Schedule Posts

bulk_schedule_posts
Destructive

Schedule up to 100 posts in one call to the same platforms and accounts. Each item supplies its own text, contentType, scheduledAt, and optional media; platforms, connection-id arrays, timezone, and platform configs are shared by every item, though an item may carry its own tiktokConfigs, youtubeConfigs, instagramConfigs, facebookConfigs, pinterestConfigs, googleBusinessConfigs or tumblrConfigs to replace the shared ones, plus its own firstComments, threadReplies, platformThumbnails and platformAspectRatios. twitterKeepLinks and linkedinConfigs are not available in bulk. Call validate_bulk_posts with the same input first to see the problems of every item without creating anything. Items are processed independently: each is validated and created like create_post, so one bad item fails alone while the rest are scheduled. Returns { totalScheduled, totalFailed, results[] } with a postId or errorMessage per item, in input order; read every row. An item with a past scheduledAt publishes immediately rather than being rejected. Call list_accounts first; TikTok needs tiktokConfigs with privacyLevel, and Pinterest takes pinterestConfigs with a boardId from list_pinterest_boards or a boardName, not both; an item whose boardName matches no board or several fails alone. Use create_post for a single post or a draft; this tool has no draft mode. These posts publish publicly to the user's social accounts: show the user every item's text, media and time plus the accounts, and get their confirmation before calling. Each call creates new posts, so calling again after an error or timeout can publish duplicates; check list_posts first.

Input Schema

NameRequiredDescriptionDefault
postsYes1 to 100 posts to schedule; each is created independently
pageIdsNoFacebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array
timezoneNoIANA timezone stored with every post for display; does not shift scheduledAtUTC
platformsYesTarget platforms shared by every item. Each needs its connection-id array (pageIds for FACEBOOK, googleBusinessConnectionIds for GOOGLE_BUSINESS)
workspaceIdNoWorkspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another
tiktokConfigsNoTikTok per-connection config. Each entry needs connectionId + privacyLevel at minimum
tumblrConfigsNoTumblr per-blog config: tags, a title and a source link. connectionId must match an entry in tumblrConnectionIds
youtubeConfigsNoYouTube per-connection config with video title, tags, privacy, etc.
facebookConfigsNoFacebook per-page config: post type, shareToStory, video title, text background, and a grid or link carousel for several images. pageId must match an entry in pageIds
instagramConfigsNoInstagram per-connection config: post type (FEED, REEL, STORY), shareToStory, collaborators, user tags, the AI info label, Reel audio, and trial reels
pinterestConfigsNoPinterest per-connection config: the board to pin to, a pin title and a destination link. Get boardId from list_pinterest_boards for that connectionId, or pass the board name as boardName instead (not both); a board belongs to one Pinterest account. A boardName that matches no board or several fails with 400. Without either the pin goes to a board named AdaptlyPost
tiktokConnectionIdsNoTikTok account connection IDs to post from
tumblrConnectionIdsNoTumblr blogs to post to, by the account id from list_accounts. TUMBLR takes text up to 32768 characters, up to 30 JPEG, PNG or GIF images (10 MB each) or one MP4 video (500 MB, up to 10 minutes), and alt text; it has no first comments, threads, per-platform thumbnails, image shapes or analytics
blueskyConnectionIdsNoBluesky account connection IDs to post from
threadsConnectionIdsNoThreads account connection IDs to post from
twitterConnectionIdsNoX (Twitter) account connection IDs to post from
youtubeConnectionIdsNoYouTube channel connection IDs to post from
googleBusinessConfigsNoGoogle Business Profile per-location config: update, event or offer, plus a button. connectionId must match an entry in googleBusinessConnectionIds. GOOGLE_BUSINESS takes TEXT or IMAGE with one JPEG or PNG image up to 5 MB, and text up to 1500 characters
linkedinConnectionIdsNoLinkedIn account connection IDs to post from
mastodonConnectionIdsNoMastodon account connection IDs to post from
telegramConnectionIdsNoTelegram channels and groups to post to, by the account id from list_accounts. TELEGRAM takes text up to 4096 characters, up to 10 images (JPEG, PNG or WebP, 10 MB each) or one MP4 or MOV video (50 MB); a caption over 1024 characters goes out as its own message after the media
instagramConnectionIdsNoInstagram account connection IDs to post from
pinterestConnectionIdsNoPinterest account connection IDs to post from
googleBusinessConnectionIdsNoGoogle Business Profile locations to post to, by the account id from list_accounts. A location without an entry in googleBusinessConfigs gets a STANDARD update

Output Schema

NameRequiredDescriptionDefault
resultNoAn object with totalScheduled, totalFailed, and results: one { postId, success, isScheduled, scheduledAt, errorMessage } per input item, in input order.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / tumblrConnectionIds / description
      Previous value: -"Tumblr blog account ids from list_accounts to post to"New value: +"Tumblr blogs to post to, by the account id from list_accounts. TUMBLR takes text up to 32768 characters, up to 30 JPEG, PNG or GIF images (10 MB each) or one MP4 video (500 MB, up to 10 minutes), and alt text; it has no first comments, threads, per-platform thumbnails, image shapes or analytics"
  2. Changed19 schema fields changed
    • changedInput schema / properties / facebookConfigs / description
      Previous value: -"Facebook per-page config: post type, shareToStory, video title and text background. pageId must match an entry in pageIds"New value: +"Facebook per-page config: post type, shareToStory, video title, text background, and a grid or link carousel for several images. pageId must match an entry in pageIds"
    • changedInput schema / properties / instagramConfigs / description
      Previous value: -"Instagram per-connection config: post type (FEED, REEL, STORY), shareToStory, collaborators, Reel audio, and trial reels"New value: +"Instagram per-connection config: post type (FEED, REEL, STORY), shareToStory, collaborators, user tags, the AI info label, Reel audio, and trial reels"
    • changedInput schema / properties / platforms / items / enum
      Previous value: -[
      -  "LINKEDIN",
      -  "YOUTUBE",
      -  "INSTAGRAM",
      -  "FACEBOOK",
      -  "TIKTOK",
      -  "PINTEREST",
      -  "THREADS",
      -  "BLUESKY",
      -  "TWITTER",
      -  "MASTODON",
      -  "GOOGLE_BUSINESS"
      -]New value: +[
      +  "LINKEDIN",
      +  "YOUTUBE",
      +  "INSTAGRAM",
      +  "FACEBOOK",
      +  "TIKTOK",
      +  "PINTEREST",
      +  "THREADS",
      +  "BLUESKY",
      +  "TWITTER",
      +  "MASTODON",
      +  "GOOGLE_BUSINESS",
      +  "TUMBLR",
      +  "TELEGRAM"
      +]
    • changedInput schema / properties / posts / items / properties / contentType / description
      Previous value: -"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls. DOCUMENT posts cannot be bulk scheduled; use create_post. CAROUSEL takes 2 or more items in mediaUrls, up to 4 on TWITTER, BLUESKY and MASTODON, 5 on PINTEREST, 10 on INSTAGRAM, FACEBOOK and THREADS, 20 on LINKEDIN and 35 on TIKTOK (JPEG or WebP photos only). INSTAGRAM and THREADS accept images and videos in the same carousel; every other platform takes images only, and YOUTUBE has no carousel. GOOGLE_BUSINESS takes TEXT or IMAGE with one JPEG or PNG image up to 5 MB, and text up to 1500 characters"New value: +"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls. DOCUMENT posts cannot be bulk scheduled; use create_post. CAROUSEL takes 2 or more items in mediaUrls, up to 4 on TWITTER, BLUESKY and MASTODON, 5 on PINTEREST, 10 on INSTAGRAM, FACEBOOK, THREADS and TELEGRAM, 20 on LINKEDIN, 30 on TUMBLR and 35 on TIKTOK (JPEG or WebP photos only). INSTAGRAM and THREADS accept images and videos in the same carousel; every other platform takes images only, and YOUTUBE has no carousel. GOOGLE_BUSINESS takes TEXT or IMAGE with one JPEG or PNG image up to 5 MB, and text up to 1500 characters. TELEGRAM takes text up to 4096 characters, up to 10 images (JPEG, PNG or WebP, 10 MB each) or one MP4 or MOV video (50 MB); a caption over 1024 characters goes out as its own message after the media"
    • addedInput schema / properties / posts / items / properties / facebookConfigs / items / properties / carouselCards
      Added value: +{
      +  "description": "One card per image, in the same order as the media, used when imageLayout is CAROUSEL. Facebook only shows your image, title and description on a card whose link points to a website the Page owns; for any other link the post fails with the error Facebook returns",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "description": {
      +        "description": "The line under the headline, such as a price or the domain. Without it Facebook uses the linked page",
      +        "maxLength": 200,
      +        "type": "string"
      +      },
      +      "link": {
      +        "description": "The http or https URL the card opens",
      +        "maxLength": 2048,
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "The card's headline. Without it Facebook uses the linked page's title",
      +        "maxLength": 100,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "link"
      +    ],
      +    "type": "object"
      +  },
      +  "maxItems": 5,
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / facebookConfigs / items / properties / imageLayout
      Added value: +{
      +  "description": "How a post with several images shows on Facebook. GRID is a photo grid. CAROUSEL is a swipeable carousel where each image is a card with its own link, and needs 2 to 5 images, no videos, postType FEED and one carouselCards entry per image; anything else is refused with 400",
      +  "enum": [
      +    "GRID",
      +    "CAROUSEL"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / posts / items / properties / firstComments / description
      Previous value: -"A comment posted from the same account right after the post goes out on a platform, one entry per platform. Available on LINKEDIN (1250 characters), TWITTER (280, as a reply), THREADS (500, as a reply), BLUESKY (300, as a reply), MASTODON (500, as a reply) and YOUTUBE (10000). A platform the post does not go to, an empty or too long comment, a second entry for one platform, a private or made for kids YouTube video and Facebook or Instagram stories are refused with 400. The comment is posted about 10 seconds after the platform publishes (60 on YouTube) and retried up to 3 times; on X it is not retried, and a lifetime-deal account pays for it like any X post. A comment that fails never fails the post: read firstCommentStatus and firstCommentError on the platform in get_post. On an update, sending the array replaces every first comment and omitting it keeps the stored ones"New value: +"A comment posted from the same account right after the post goes out on a platform, one entry per platform. Available on LINKEDIN (1250 characters), TWITTER (280, as a reply), THREADS (500, as a reply), BLUESKY (300, as a reply), MASTODON (500, as a reply), YOUTUBE (10000), FACEBOOK (8000) and INSTAGRAM (2200). A platform the post does not go to, an empty or too long comment, a second entry for one platform, a platform that also has threadReplies, a private or made for kids YouTube video and Facebook or Instagram stories are refused with 400. The comment is posted about 10 seconds after the platform publishes (60 on YouTube) and retried up to 3 times; on X it is not retried, and a lifetime-deal account pays for it like any X post. A Facebook Page or Instagram account connected before first comments came to them must be reconnected once; until then its comment fails and firstCommentError says to reconnect. A comment that fails never fails the post: read firstCommentStatus and firstCommentError on the platform in get_post. On an update, sending the array replaces every first comment and omitting it keeps the stored ones"
    • changedInput schema / properties / posts / items / properties / firstComments / items / properties / platform / enum
      Previous value: -[
      -  "LINKEDIN",
      -  "TWITTER",
      -  "THREADS",
      -  "BLUESKY",
      -  "MASTODON",
      -  "YOUTUBE"
      -]New value: +[
      +  "LINKEDIN",
      +  "TWITTER",
      +  "THREADS",
      +  "BLUESKY",
      +  "MASTODON",
      +  "YOUTUBE",
      +  "FACEBOOK",
      +  "INSTAGRAM"
      +]
    • addedInput schema / properties / posts / items / properties / instagramConfigs / items / properties / aiGenerated
      Added value: +{
      +  "description": "Disclose that the post was made or edited with AI. Instagram shows its \"AI info\" label on the post. Works on images, carousels, reels and stories, and a story made with shareToStory carries the label too. Omit it or send false for no label",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / posts / items / properties / instagramConfigs / items / properties / userTags
      Added value: +{
      +  "description": "Public Instagram accounts tagged in the media, up to 20. Works on a single image, a single video (published as a Reel) or a single story; a carousel or several stories with tags is refused with 400. On a feed image every tag needs x and y; on a story they are optional, and on a video they are ignored because the person is tagged on the video as a whole. A leading @ is stripped and a repeated username keeps its first entry. If Instagram refuses a tag because the account is private or does not exist, the post goes out without its tags and instagramUntaggedUsernames in get_post lists the refused usernames",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "username": {
      +        "description": "The public Instagram username to tag",
      +        "pattern": "^@?[A-Za-z0-9._]{1,30}$",
      +        "type": "string"
      +      },
      +      "x": {
      +        "description": "Horizontal position of the tag on the image, from 0 (left edge) to 1 (right edge)",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "y": {
      +        "description": "Vertical position of the tag on the image, from 0 (top edge) to 1 (bottom edge)",
      +        "maximum": 1,
      +        "minimum": 0,
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "username"
      +    ],
      +    "type": "object"
      +  },
      +  "maxItems": 20,
      +  "type": "array"
      +}
    • changedInput schema / properties / posts / items / properties / mediaAltTexts / description
      Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube, Google Business Profile and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, Tumblr, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube, Google Business Profile and videos ignore it"
    • changedInput schema / properties / posts / items / properties / platformThumbnails / description
      Previous value: -"A different thumbnail for one platform of a VIDEO post, one entry per platform. A platform without an entry uses the post-level thumbnailUrl and thumbnailTimestampMs. YOUTUBE, FACEBOOK and LINKEDIN take an image (thumbnailUrl); INSTAGRAM and PINTEREST take an image or a frame (thumbnailTimestampMs), the image winning when both are sent; TIKTOK takes only a frame. Posts that are not videos, Facebook and Instagram stories, a second entry for one platform and an entry the platform cannot use are refused with 400. On an update, sending the array replaces every override and omitting it keeps the stored ones"New value: +"A different thumbnail for one platform of a VIDEO post, one entry per platform. A platform without an entry uses the post-level thumbnailUrl and thumbnailTimestampMs. YOUTUBE, FACEBOOK, LINKEDIN and TELEGRAM take an image (thumbnailUrl); INSTAGRAM and PINTEREST take an image or a frame (thumbnailTimestampMs), the image winning when both are sent; TIKTOK takes only a frame. Posts that are not videos, Facebook and Instagram stories, a second entry for one platform and an entry the platform cannot use are refused with 400. On an update, sending the array replaces every override and omitting it keeps the stored ones"
    • changedInput schema / properties / posts / items / properties / platformThumbnails / items / properties / platform / enum
      Previous value: -[
      -  "YOUTUBE",
      -  "FACEBOOK",
      -  "LINKEDIN",
      -  "INSTAGRAM",
      -  "PINTEREST",
      -  "TIKTOK"
      -]New value: +[
      +  "YOUTUBE",
      +  "FACEBOOK",
      +  "LINKEDIN",
      +  "TELEGRAM",
      +  "INSTAGRAM",
      +  "PINTEREST",
      +  "TIKTOK"
      +]
    • addedInput schema / properties / posts / items / properties / threadReplies
      Added value: +{
      +  "description": "Turns the post into a thread: the post opens it and each text is published as a reply to the one before, from the same account, one entry per platform. Available on TWITTER (280 characters per reply, or the account's own limit on X Premium), THREADS (500), BLUESKY (300) and MASTODON (500, or the instance's limit), up to 25 replies. A platform the post does not go to, an empty or too long reply, more than 25 replies, a second entry for one platform and a platform that also has a first comment are refused with 400. An entry with an empty texts array removes the thread. Replies start about 10 seconds after the platform publishes, 2 seconds apart. A failed run is retried up to 3 times and resumes after the last reply that went out; on X it is not retried, and a lifetime-deal account pays for each reply like any X post. A thread that fails never fails the post: read threadStatus, threadReplyIds and threadError on the platform in get_post. On an update, sending the array replaces every thread and omitting it keeps the stored ones",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "platform": {
      +        "enum": [
      +          "TWITTER",
      +          "THREADS",
      +          "BLUESKY",
      +          "MASTODON"
      +        ],
      +        "type": "string"
      +      },
      +      "texts": {
      +        "description": "The replies in order, each trimmed. The limit per reply depends on the platform, see threadReplies",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 25,
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "platform",
      +      "texts"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / tumblrConfigs
      Added value: +{
      +  "description": "Tumblr config for this item only, such as its own tags; replaces the batch-level tumblrConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "connectionId": {
      +        "description": "Tumblr blog account id from list_accounts",
      +        "type": "string"
      +      },
      +      "sourceUrl": {
      +        "description": "Shown as the source link of the post",
      +        "maxLength": 2048,
      +        "type": "string"
      +      },
      +      "tags": {
      +        "description": "Tumblr tags, without commas, up to 30. A leading # is stripped and duplicates are dropped, ignoring case",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 30,
      +        "type": "array"
      +      },
      +      "title": {
      +        "description": "Shown as a heading above the media and the text",
      +        "maxLength": 4096,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / youtubeConfigs / items / properties / aiGenerated
      Added value: +{
      +  "description": "Disclose altered or synthetic content, such as an AI voice, an AI avatar or realistic footage that was generated or edited. YouTube shows its \"Altered or synthetic content\" label on the video. Omit it or send false for no label",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / telegramConnectionIds
      Added value: +{
      +  "description": "Telegram channels and groups to post to, by the account id from list_accounts. TELEGRAM takes text up to 4096 characters, up to 10 images (JPEG, PNG or WebP, 10 MB each) or one MP4 or MOV video (50 MB); a caption over 1024 characters goes out as its own message after the media",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / tumblrConfigs
      Added value: +{
      +  "description": "Tumblr per-blog config: tags, a title and a source link. connectionId must match an entry in tumblrConnectionIds",
      +  "items": {
      +    "$ref": "#/properties/posts/items/properties/tumblrConfigs/items"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / tumblrConnectionIds
      Added value: +{
      +  "description": "Tumblr blog account ids from list_accounts to post to",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  3. Changed4 schema fields changed
    • changedInput schema / properties / pinterestConfigs / description
      Previous value: -"Pinterest per-connection config: the board to pin to, a pin title and a destination link. Get boardId from list_pinterest_boards for that connectionId; a board belongs to one Pinterest account. Without boardId the pin goes to a board named AdaptlyPost"New value: +"Pinterest per-connection config: the board to pin to, a pin title and a destination link. Get boardId from list_pinterest_boards for that connectionId, or pass the board name as boardName instead (not both); a board belongs to one Pinterest account. A boardName that matches no board or several fails with 400. Without either the pin goes to a board named AdaptlyPost"
    • changedInput schema / properties / posts / items / properties / pinterestConfigs / description
      Previous value: -"Pinterest config for this item only, such as its own title or link; replaces the batch-level pinterestConfigs"New value: +"Pinterest config for this item only, such as its own board, title or link; replaces the batch-level pinterestConfigs"
    • changedInput schema / properties / posts / items / properties / pinterestConfigs / items / properties / boardId / description
      Previous value: -"Board id from list_pinterest_boards. Leave out to pin to a public board named AdaptlyPost, created on the account the first time it is needed"New value: +"Board id from list_pinterest_boards. Leave out boardId and boardName to pin to a public board named AdaptlyPost, created on the account the first time it is needed"
    • addedInput schema / properties / posts / items / properties / pinterestConfigs / items / properties / boardName
      Added value: +{
      +  "description": "The board's name, instead of boardId; never send both. Matched against this account's boards, exact first, then case-insensitive. A name no board has, or one several boards share, fails with 400 and never falls back to another board",
      +  "maxLength": 180,
      +  "minLength": 1,
      +  "type": "string"
      +}
  4. Changed3 schema fields changed
    • changedInput schema / properties / pinterestConfigs / description
      Previous value: -"Pinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id"New value: +"Pinterest per-connection config: the board to pin to, a pin title and a destination link. Get boardId from list_pinterest_boards for that connectionId; a board belongs to one Pinterest account. Without boardId the pin goes to a board named AdaptlyPost"
    • changedInput schema / properties / posts / items / properties / pinterestConfigs / items / properties / boardId / description
      Previous value: -"Pinterest board ID to pin to (required)"New value: +"Board id from list_pinterest_boards. Leave out to pin to a public board named AdaptlyPost, created on the account the first time it is needed"
    • changedInput schema / properties / posts / items / properties / pinterestConfigs / items / required
      Previous value: -[
      -  "connectionId",
      -  "boardId"
      -]New value: +[
      +  "connectionId"
      +]
  5. Changed23 schema fields changed
    • changedInput schema / properties / facebookConfigs / description
      Previous value: -"Facebook per-page config with post type and video title. pageId must match an entry in pageIds"New value: +"Facebook per-page config: post type, shareToStory, video title and text background. pageId must match an entry in pageIds"
    • addedInput schema / properties / googleBusinessConfigs
      Added value: +{
      +  "description": "Google Business Profile per-location config: update, event or offer, plus a button. connectionId must match an entry in googleBusinessConnectionIds. GOOGLE_BUSINESS takes TEXT or IMAGE with one JPEG or PNG image up to 5 MB, and text up to 1500 characters",
      +  "items": {
      +    "$ref": "#/properties/posts/items/properties/googleBusinessConfigs/items"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / googleBusinessConnectionIds
      Added value: +{
      +  "description": "Google Business Profile locations to post to, by the account id from list_accounts. A location without an entry in googleBusinessConfigs gets a STANDARD update",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / instagramConfigs / description
      Previous value: -"Instagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel"New value: +"Instagram per-connection config: post type (FEED, REEL, STORY), shareToStory, collaborators, Reel audio, and trial reels"
    • changedInput schema / properties / platforms / description
      Previous value: -"Target platforms shared by every item. Each needs its connection-id array (pageIds for FACEBOOK)"New value: +"Target platforms shared by every item. Each needs its connection-id array (pageIds for FACEBOOK, googleBusinessConnectionIds for GOOGLE_BUSINESS)"
    • changedInput schema / properties / platforms / items / enum
      Previous value: -[
      -  "LINKEDIN",
      -  "YOUTUBE",
      -  "INSTAGRAM",
      -  "FACEBOOK",
      -  "TIKTOK",
      -  "PINTEREST",
      -  "THREADS",
      -  "BLUESKY",
      -  "TWITTER",
      -  "MASTODON"
      -]New value: +[
      +  "LINKEDIN",
      +  "YOUTUBE",
      +  "INSTAGRAM",
      +  "FACEBOOK",
      +  "TIKTOK",
      +  "PINTEREST",
      +  "THREADS",
      +  "BLUESKY",
      +  "TWITTER",
      +  "MASTODON",
      +  "GOOGLE_BUSINESS"
      +]
    • changedInput schema / properties / posts / items / properties / contentType / description
      Previous value: -"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls. DOCUMENT posts cannot be bulk scheduled; use create_post"New value: +"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls. DOCUMENT posts cannot be bulk scheduled; use create_post. CAROUSEL takes 2 or more items in mediaUrls, up to 4 on TWITTER, BLUESKY and MASTODON, 5 on PINTEREST, 10 on INSTAGRAM, FACEBOOK and THREADS, 20 on LINKEDIN and 35 on TIKTOK (JPEG or WebP photos only). INSTAGRAM and THREADS accept images and videos in the same carousel; every other platform takes images only, and YOUTUBE has no carousel. GOOGLE_BUSINESS takes TEXT or IMAGE with one JPEG or PNG image up to 5 MB, and text up to 1500 characters"
    • changedInput schema / properties / posts / items / properties / facebookConfigs / items / properties / postType / description
      Previous value: -"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400"New value: +"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE, VIDEO or CAROUSEL (a CAROUSEL story publishes each media item as its own story, in order). Any other combination is refused with 400"
    • addedInput schema / properties / posts / items / properties / facebookConfigs / items / properties / shareToStory
      Added value: +{
      +  "description": "Also publish the same media as a story on this page, next to the FEED or REEL post. The story shows as its own entry in platforms with postType STORY, so it succeeds, fails and retries on its own. It skips the caption, video title and text background, needs IMAGE, VIDEO or CAROUSEL, and a video must fit the story length limit (60 seconds). Ignored when postType is STORY",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / posts / items / properties / facebookConfigs / items / properties / textFormatPresetId
      Added value: +{
      +  "description": "Facebook's id for a colored text background (for example 106018623298955 is solid purple, 249307305544279 is a red to blue gradient). Only for contentType TEXT posts with no media and text up to 130 characters; anything else is refused with 400. Links in the text show without a preview. If Facebook refuses the background, the post goes out as plain text",
      +  "pattern": "^\\d{1,20}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / posts / items / properties / firstComments
      Added value: +{
      +  "description": "A comment posted from the same account right after the post goes out on a platform, one entry per platform. Available on LINKEDIN (1250 characters), TWITTER (280, as a reply), THREADS (500, as a reply), BLUESKY (300, as a reply), MASTODON (500, as a reply) and YOUTUBE (10000). A platform the post does not go to, an empty or too long comment, a second entry for one platform, a private or made for kids YouTube video and Facebook or Instagram stories are refused with 400. The comment is posted about 10 seconds after the platform publishes (60 on YouTube) and retried up to 3 times; on X it is not retried, and a lifetime-deal account pays for it like any X post. A comment that fails never fails the post: read firstCommentStatus and firstCommentError on the platform in get_post. On an update, sending the array replaces every first comment and omitting it keeps the stored ones",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "platform": {
      +        "enum": [
      +          "LINKEDIN",
      +          "TWITTER",
      +          "THREADS",
      +          "BLUESKY",
      +          "MASTODON",
      +          "YOUTUBE"
      +        ],
      +        "type": "string"
      +      },
      +      "text": {
      +        "description": "The comment's text, trimmed. The limit depends on the platform, see firstComments",
      +        "maxLength": 10000,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "platform",
      +      "text"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / googleBusinessConfigs
      Added value: +{
      +  "description": "Google Business Profile config for this item only, such as its own event or offer; replaces the batch-level googleBusinessConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "callToActionType": {
      +        "description": "Button shown on the post. Every type except CALL needs callToActionUrl; CALL dials the phone number on the Business Profile",
      +        "enum": [
      +          "BOOK",
      +          "ORDER",
      +          "SHOP",
      +          "LEARN_MORE",
      +          "SIGN_UP",
      +          "CALL"
      +        ],
      +        "type": "string"
      +      },
      +      "callToActionUrl": {
      +        "description": "Ignored when callToActionType is CALL",
      +        "format": "uri",
      +        "type": "string"
      +      },
      +      "connectionId": {
      +        "description": "Google Business Profile account id from list_accounts",
      +        "type": "string"
      +      },
      +      "eventEnd": {
      +        "$ref": "#/properties/posts/items/properties/googleBusinessConfigs/items/properties/eventStart",
      +        "description": "YYYY-MM-DD or YYYY-MM-DDTHH:mm in the business's local time, with no offset (e.g. \"2026-10-01T21:00\")"
      +      },
      +      "eventStart": {
      +        "description": "YYYY-MM-DD or YYYY-MM-DDTHH:mm in the business's local time, with no offset (e.g. \"2026-10-01T18:00\"). Google reads event times in the location's time zone",
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2})?$",
      +        "type": "string"
      +      },
      +      "eventTitle": {
      +        "description": "Title of the event or offer",
      +        "type": "string"
      +      },
      +      "offerCouponCode": {
      +        "description": "OFFER only: coupon code",
      +        "type": "string"
      +      },
      +      "offerRedeemUrl": {
      +        "description": "OFFER only: where the offer is redeemed",
      +        "format": "uri",
      +        "type": "string"
      +      },
      +      "offerTerms": {
      +        "description": "OFFER only: terms and conditions",
      +        "type": "string"
      +      },
      +      "topicType": {
      +        "description": "STANDARD is an update. EVENT and OFFER need eventTitle, eventStart and eventEnd",
      +        "enum": [
      +          "STANDARD",
      +          "EVENT",
      +          "OFFER"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId",
      +      "topicType"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / instagramConfigs / items / properties / audio
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Music or an original sound from Instagram's audio library, added to the Reel when it is published. Needs contentType VIDEO and a postType other than STORY, and only works for accounts with supportsInstagramAudio: true in list_accounts (connected through Facebook). Find ids with search_instagram_audio",
      +  "properties": {
      +    "artist": {
      +      "description": "Artist or creator, stored for display only",
      +      "maxLength": 255,
      +      "type": "string"
      +    },
      +    "audioId": {
      +      "description": "audioId from search_instagram_audio",
      +      "maxLength": 64,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "audioVolume": {
      +      "description": "Volume of the added audio, 1 to 100. Defaults to 100",
      +      "maximum": 100,
      +      "minimum": 1,
      +      "type": "integer"
      +    },
      +    "title": {
      +      "description": "Track title, stored for display only",
      +      "maxLength": 255,
      +      "type": "string"
      +    },
      +    "videoVolume": {
      +      "description": "Volume of the video's own sound, 1 to 100. Defaults to 100",
      +      "maximum": 100,
      +      "minimum": 1,
      +      "type": "integer"
      +    }
      +  },
      +  "required": [
      +    "audioId"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / posts / items / properties / instagramConfigs / items / properties / collaborators
      Added value: +{
      +  "description": "Instagram usernames invited as collaborators (Instagram Collab), up to 3. A leading @ is stripped and duplicates are dropped. Works on feed images, carousels and reels; a story or a trial reel with collaborators is refused with 400. Each collaborator gets an invite in Instagram and must accept it before the post shows on their profile",
      +  "items": {
      +    "pattern": "^@?[A-Za-z0-9._]{1,30}$",
      +    "type": "string"
      +  },
      +  "maxItems": 3,
      +  "type": "array"
      +}
    • changedInput schema / properties / posts / items / properties / instagramConfigs / items / properties / postType / description
      Previous value: -"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400"New value: +"Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE, VIDEO or CAROUSEL (a CAROUSEL story publishes each media item as its own story, in order). Any other combination is refused with 400"
    • addedInput schema / properties / posts / items / properties / instagramConfigs / items / properties / shareToStory
      Added value: +{
      +  "description": "Also publish the same media as a story on this account, next to the FEED or REEL post. The story shows as its own entry in platforms with postType STORY, so it succeeds, fails and retries on its own. It skips the caption, first comment, cover, collaborators, trial and audio, needs IMAGE, VIDEO or CAROUSEL, and a video must fit the story length limit (60 seconds). Ignored when postType is STORY",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / posts / items / properties / mediaAltTexts / description
      Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube, Google Business Profile and videos ignore it"
    • addedInput schema / properties / posts / items / properties / platformAspectRatios
      Added value: +{
      +  "description": "Reframe every image of an IMAGE or CAROUSEL post to one shape on a platform, one entry per platform. INSTAGRAM takes SQUARE, PORTRAIT or LANDSCAPE (Instagram refuses 9:16 feed and carousel images); TIKTOK takes all four. Video posts, Instagram stories and a second entry for the same platform are refused with 400. Omit a platform to keep its images as uploaded. On an update it applies to the mediaUrls sent in the same request",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "aspectRatio": {
      +        "description": "SQUARE is 1:1, PORTRAIT 4:5, VERTICAL 9:16 and LANDSCAPE 1.91:1",
      +        "enum": [
      +          "SQUARE",
      +          "PORTRAIT",
      +          "VERTICAL",
      +          "LANDSCAPE"
      +        ],
      +        "type": "string"
      +      },
      +      "fit": {
      +        "description": "How an image of another shape reaches the ratio. CROP (the default) cuts it from the center; PAD keeps the whole image and fills the rest with a blurred copy of it",
      +        "enum": [
      +          "CROP",
      +          "PAD"
      +        ],
      +        "type": "string"
      +      },
      +      "platform": {
      +        "enum": [
      +          "INSTAGRAM",
      +          "TIKTOK"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "platform",
      +      "aspectRatio"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / platformTexts / items / properties / text / description
      Added value: +"On LinkedIn, mention a company page with @[Page Name](urn:li:organization:<id>), using the page name exactly as LinkedIn shows it"
    • addedInput schema / properties / posts / items / properties / platformThumbnails
      Added value: +{
      +  "description": "A different thumbnail for one platform of a VIDEO post, one entry per platform. A platform without an entry uses the post-level thumbnailUrl and thumbnailTimestampMs. YOUTUBE, FACEBOOK and LINKEDIN take an image (thumbnailUrl); INSTAGRAM and PINTEREST take an image or a frame (thumbnailTimestampMs), the image winning when both are sent; TIKTOK takes only a frame. Posts that are not videos, Facebook and Instagram stories, a second entry for one platform and an entry the platform cannot use are refused with 400. On an update, sending the array replaces every override and omitting it keeps the stored ones",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "platform": {
      +        "enum": [
      +          "YOUTUBE",
      +          "FACEBOOK",
      +          "LINKEDIN",
      +          "INSTAGRAM",
      +          "PINTEREST",
      +          "TIKTOK"
      +        ],
      +        "type": "string"
      +      },
      +      "thumbnailTimestampMs": {
      +        "description": "The video frame (ms from the start) to use as this platform's thumbnail",
      +        "minimum": 0,
      +        "type": "integer"
      +      },
      +      "thumbnailUrl": {
      +        "description": "The image to use as this platform's thumbnail, an https URL or an image data URI",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "platform"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / posts / items / properties / text / description
      Previous value: -"Post text/caption"New value: +"Post text/caption. On LinkedIn, mention a company page with @[Page Name](urn:li:organization:<id>), using the page name exactly as LinkedIn shows it"
    • changedInput schema / properties / posts / items / properties / thumbnailTimestampMs / description
      Previous value: -"Thumbnail timestamp in ms"New value: +"Video frame timestamp (ms) to use as the thumbnail, used by INSTAGRAM, PINTEREST and TIKTOK unless platformThumbnails overrides it"
    • changedInput schema / properties / posts / items / properties / thumbnailUrl / description
      Previous value: -"Custom thumbnail image URL"New value: +"Video thumbnail as an https URL or an image data URI, used on every platform that takes one unless platformThumbnails overrides it"
  6. Changed2 schema fields changed
    • removedInput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
    • removedOutput schema / $schema
      Removed value: -"http://json-schema.org/draft-07/schema#"
  7. Changed33 schema fields changed
    • addedInput schema / properties / facebookConfigs / items / $ref
      Added value: +"#/properties/posts/items/properties/facebookConfigs/items"
    • removedInput schema / properties / facebookConfigs / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / facebookConfigs / items / properties
      Removed value: -{
      -  "pageId": {
      -    "description": "Facebook page ID from list_accounts",
      -    "type": "string"
      -  },
      -  "postType": {
      -    "description": "Facebook post type — FEED, REEL, or STORY",
      -    "enum": [
      -      "FEED",
      -      "REEL",
      -      "STORY"
      -    ],
      -    "type": "string"
      -  },
      -  "videoTitle": {
      -    "description": "Video title for Facebook (max 255 chars)",
      -    "maxLength": 255,
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / facebookConfigs / items / required
      Removed value: -[
      -  "pageId"
      -]
    • removedInput schema / properties / facebookConfigs / items / type
      Removed value: -"object"
    • addedInput schema / properties / instagramConfigs / items / $ref
      Added value: +"#/properties/posts/items/properties/instagramConfigs/items"
    • removedInput schema / properties / instagramConfigs / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / instagramConfigs / items / properties
      Removed value: -{
      -  "connectionId": {
      -    "description": "Instagram connection ID from list_accounts",
      -    "type": "string"
      -  },
      -  "postType": {
      -    "description": "Instagram post type — FEED, REEL, or STORY",
      -    "enum": [
      -      "FEED",
      -      "REEL",
      -      "STORY"
      -    ],
      -    "type": "string"
      -  },
      -  "trialGraduation": {
      -    "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
      -    "enum": [
      -      "MANUAL",
      -      "SS_PERFORMANCE"
      -    ],
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / instagramConfigs / items / required
      Removed value: -[
      -  "connectionId"
      -]
    • removedInput schema / properties / instagramConfigs / items / type
      Removed value: -"object"
    • addedInput schema / properties / pinterestConfigs / items / $ref
      Added value: +"#/properties/posts/items/properties/pinterestConfigs/items"
    • removedInput schema / properties / pinterestConfigs / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / pinterestConfigs / items / properties
      Removed value: -{
      -  "boardId": {
      -    "description": "Pinterest board ID to pin to (required)",
      -    "type": "string"
      -  },
      -  "connectionId": {
      -    "description": "Pinterest connection ID from list_accounts",
      -    "type": "string"
      -  },
      -  "link": {
      -    "description": "Destination URL for the pin",
      -    "type": "string"
      -  },
      -  "title": {
      -    "description": "Pin title (max 100 chars)",
      -    "maxLength": 100,
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / pinterestConfigs / items / required
      Removed value: -[
      -  "connectionId",
      -  "boardId"
      -]
    • removedInput schema / properties / pinterestConfigs / items / type
      Removed value: -"object"
    • addedInput schema / properties / posts / items / properties / facebookConfigs
      Added value: +{
      +  "description": "Facebook config for this item only; replaces the batch-level facebookConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "pageId": {
      +        "description": "Facebook page ID from list_accounts",
      +        "type": "string"
      +      },
      +      "postType": {
      +        "description": "Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400",
      +        "enum": [
      +          "FEED",
      +          "REEL",
      +          "STORY"
      +        ],
      +        "type": "string"
      +      },
      +      "videoTitle": {
      +        "description": "Video title for Facebook (max 255 chars)",
      +        "maxLength": 255,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "pageId"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / instagramConfigs
      Added value: +{
      +  "description": "Instagram config for this item only; replaces the batch-level instagramConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "connectionId": {
      +        "description": "Instagram connection ID from list_accounts",
      +        "type": "string"
      +      },
      +      "postType": {
      +        "description": "Where the post goes: FEED works with every content type, REEL needs contentType VIDEO, STORY needs IMAGE or VIDEO. Any other combination is refused with 400",
      +        "enum": [
      +          "FEED",
      +          "REEL",
      +          "STORY"
      +        ],
      +        "type": "string"
      +      },
      +      "trialGraduation": {
      +        "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
      +        "enum": [
      +          "MANUAL",
      +          "SS_PERFORMANCE"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / pinterestConfigs
      Added value: +{
      +  "description": "Pinterest config for this item only, such as its own title or link; replaces the batch-level pinterestConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "boardId": {
      +        "description": "Pinterest board ID to pin to (required)",
      +        "type": "string"
      +      },
      +      "connectionId": {
      +        "description": "Pinterest connection ID from list_accounts",
      +        "type": "string"
      +      },
      +      "link": {
      +        "description": "Destination URL for the pin",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "Pin title (max 100 chars)",
      +        "maxLength": 100,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId",
      +      "boardId"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / tiktokConfigs
      Added value: +{
      +  "description": "TikTok config for this item only; replaces the batch-level tiktokConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "aiGenerated": {
      +        "description": "Label content as AI-generated",
      +        "type": "boolean"
      +      },
      +      "allowComments": {
      +        "description": "Allow comments on the TikTok post",
      +        "type": "boolean"
      +      },
      +      "allowDuet": {
      +        "description": "Allow other users to Duet this video",
      +        "type": "boolean"
      +      },
      +      "allowStitch": {
      +        "description": "Allow other users to Stitch this video",
      +        "type": "boolean"
      +      },
      +      "autoAddMusic": {
      +        "description": "Let TikTok auto-add music to the video",
      +        "type": "boolean"
      +      },
      +      "brandedContent": {
      +        "description": "Disclose as branded content (paid partnership)",
      +        "type": "boolean"
      +      },
      +      "brandedContentOwnBrand": {
      +        "description": "Disclose as promoting your own brand",
      +        "type": "boolean"
      +      },
      +      "caption": {
      +        "description": "TikTok-specific caption (max 2200 chars)",
      +        "maxLength": 2200,
      +        "type": "string"
      +      },
      +      "connectionId": {
      +        "description": "TikTok connection ID from list_accounts",
      +        "type": "string"
      +      },
      +      "privacyLevel": {
      +        "description": "TikTok privacy level",
      +        "enum": [
      +          "PUBLIC_TO_EVERYONE",
      +          "MUTUAL_FOLLOW_FRIENDS",
      +          "FOLLOWER_OF_CREATOR",
      +          "SELF_ONLY"
      +        ],
      +        "type": "string"
      +      },
      +      "sendAsDraft": {
      +        "description": "Save as TikTok draft so the user can add trending sounds before publishing",
      +        "type": "boolean"
      +      },
      +      "title": {
      +        "description": "Video title (max 90 chars)",
      +        "maxLength": 90,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId",
      +      "privacyLevel"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / items / properties / youtubeConfigs
      Added value: +{
      +  "description": "YouTube config for this item only, such as its own videoTitle; replaces the batch-level youtubeConfigs",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "allowEmbedding": {
      +        "description": "Allow embedding the video on other sites",
      +        "type": "boolean"
      +      },
      +      "categoryId": {
      +        "description": "YouTube category ID",
      +        "type": "string"
      +      },
      +      "connectionId": {
      +        "description": "YouTube connection ID from list_accounts",
      +        "type": "string"
      +      },
      +      "license": {
      +        "description": "Video license type",
      +        "enum": [
      +          "youtube",
      +          "creativeCommon"
      +        ],
      +        "type": "string"
      +      },
      +      "madeForKids": {
      +        "description": "Mark the video as made for kids (COPPA)",
      +        "type": "boolean"
      +      },
      +      "notifySubscribers": {
      +        "description": "Notify channel subscribers about the upload",
      +        "type": "boolean"
      +      },
      +      "playlistId": {
      +        "description": "Add video to this playlist",
      +        "type": "string"
      +      },
      +      "postType": {
      +        "description": "VIDEO for long-form, SHORTS for YouTube Shorts",
      +        "enum": [
      +          "VIDEO",
      +          "SHORTS"
      +        ],
      +        "type": "string"
      +      },
      +      "privacyStatus": {
      +        "description": "Video privacy status",
      +        "enum": [
      +          "public",
      +          "private",
      +          "unlisted"
      +        ],
      +        "type": "string"
      +      },
      +      "tags": {
      +        "description": "Video tags (max 20)",
      +        "items": {
      +          "type": "string"
      +        },
      +        "maxItems": 20,
      +        "type": "array"
      +      },
      +      "videoTitle": {
      +        "description": "YouTube video title (max 100 chars)",
      +        "maxLength": 100,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / properties / posts / maxItems
      Added value: +100
    • addedInput schema / properties / posts / minItems
      Added value: +1
    • addedInput schema / properties / tiktokConfigs / items / $ref
      Added value: +"#/properties/posts/items/properties/tiktokConfigs/items"
    • removedInput schema / properties / tiktokConfigs / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / tiktokConfigs / items / properties
      Removed value: -{
      -  "aiGenerated": {
      -    "description": "Label content as AI-generated",
      -    "type": "boolean"
      -  },
      -  "allowComments": {
      -    "description": "Allow comments on the TikTok post",
      -    "type": "boolean"
      -  },
      -  "allowDuet": {
      -    "description": "Allow other users to Duet this video",
      -    "type": "boolean"
      -  },
      -  "allowStitch": {
      -    "description": "Allow other users to Stitch this video",
      -    "type": "boolean"
      -  },
      -  "autoAddMusic": {
      -    "description": "Let TikTok auto-add music to the video",
      -    "type": "boolean"
      -  },
      -  "brandedContent": {
      -    "description": "Disclose as branded content (paid partnership)",
      -    "type": "boolean"
      -  },
      -  "brandedContentOwnBrand": {
      -    "description": "Disclose as promoting your own brand",
      -    "type": "boolean"
      -  },
      -  "caption": {
      -    "description": "TikTok-specific caption (max 2200 chars)",
      -    "maxLength": 2200,
      -    "type": "string"
      -  },
      -  "connectionId": {
      -    "description": "TikTok connection ID from list_accounts",
      -    "type": "string"
      -  },
      -  "privacyLevel": {
      -    "description": "TikTok privacy level",
      -    "enum": [
      -      "PUBLIC_TO_EVERYONE",
      -      "MUTUAL_FOLLOW_FRIENDS",
      -      "FOLLOWER_OF_CREATOR",
      -      "SELF_ONLY"
      -    ],
      -    "type": "string"
      -  },
      -  "sendAsDraft": {
      -    "description": "Save as TikTok draft so the user can add trending sounds before publishing",
      -    "type": "boolean"
      -  },
      -  "title": {
      -    "description": "Video title (max 90 chars)",
      -    "maxLength": 90,
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / tiktokConfigs / items / required
      Removed value: -[
      -  "connectionId",
      -  "privacyLevel"
      -]
    • removedInput schema / properties / tiktokConfigs / items / type
      Removed value: -"object"
    • changedInput schema / properties / workspaceId / description
      Previous value: -"Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"New value: +"Workspace to act in: an id from list_workspaces. Omit to act in the workspace list_workspaces marks current. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another"
    • addedInput schema / properties / youtubeConfigs / items / $ref
      Added value: +"#/properties/posts/items/properties/youtubeConfigs/items"
    • removedInput schema / properties / youtubeConfigs / items / additionalProperties
      Removed value: -false
    • removedInput schema / properties / youtubeConfigs / items / properties
      Removed value: -{
      -  "allowEmbedding": {
      -    "description": "Allow embedding the video on other sites",
      -    "type": "boolean"
      -  },
      -  "categoryId": {
      -    "description": "YouTube category ID",
      -    "type": "string"
      -  },
      -  "connectionId": {
      -    "description": "YouTube connection ID from list_accounts",
      -    "type": "string"
      -  },
      -  "license": {
      -    "description": "Video license type",
      -    "enum": [
      -      "youtube",
      -      "creativeCommon"
      -    ],
      -    "type": "string"
      -  },
      -  "madeForKids": {
      -    "description": "Mark the video as made for kids (COPPA)",
      -    "type": "boolean"
      -  },
      -  "notifySubscribers": {
      -    "description": "Notify channel subscribers about the upload",
      -    "type": "boolean"
      -  },
      -  "playlistId": {
      -    "description": "Add video to this playlist",
      -    "type": "string"
      -  },
      -  "postType": {
      -    "description": "VIDEO for long-form, SHORTS for YouTube Shorts",
      -    "enum": [
      -      "VIDEO",
      -      "SHORTS"
      -    ],
      -    "type": "string"
      -  },
      -  "privacyStatus": {
      -    "description": "Video privacy status",
      -    "enum": [
      -      "public",
      -      "private",
      -      "unlisted"
      -    ],
      -    "type": "string"
      -  },
      -  "tags": {
      -    "description": "Video tags (max 20)",
      -    "items": {
      -      "type": "string"
      -    },
      -    "maxItems": 20,
      -    "type": "array"
      -  },
      -  "videoTitle": {
      -    "description": "YouTube video title (max 100 chars)",
      -    "maxLength": 100,
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / youtubeConfigs / items / required
      Removed value: -[
      -  "connectionId"
      -]
    • removedInput schema / properties / youtubeConfigs / items / type
      Removed value: -"object"
  8. Changed1 schema field changed
    • addedInput schema / properties / workspaceId
      Added value: +{
      +  "description": "Workspace to act in: an id from list_workspaces. Omit to use the default workspace. Use the same workspaceId for every call about the same workspace, since ids from one workspace (accounts, posts, uploads) do not exist in another",
      +  "type": "string"
      +}
  9. Changed2 schema fields changed
    • changedInput schema / properties / instagramConfigs / description
      Previous value: -"Instagram per-connection config to set post type (FEED, REEL, STORY)"New value: +"Instagram per-connection config to set post type (FEED, REEL, STORY) and publish a reel as a trial reel"
    • addedInput schema / properties / instagramConfigs / items / properties / trialGraduation
      Added value: +{
      +  "description": "Publish a video reel as a trial reel: Instagram shows it to non-followers first and keeps it off followers' feeds and the profile grid until it is shared. MANUAL means the account owner shares it from the Instagram app; SS_PERFORMANCE means Instagram shares it if it performs well. Only for a single video posted as a reel or feed video, never a story, image or carousel (400 otherwise). Needs a professional account Instagram has enabled for trial reels; otherwise that platform fails with a message saying so",
      +  "enum": [
      +    "MANUAL",
      +    "SS_PERFORMANCE"
      +  ],
      +  "type": "string"
      +}
  10. Changed1 schema field changed
    • changedInput schema / properties / posts / items / properties / contentType / description
      Previous value: -"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls"New value: +"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls. DOCUMENT posts cannot be bulk scheduled; use create_post"
  11. Changed3 schema fields changed
    • addedInput schema / properties / mastodonConnectionIds
      Added value: +{
      +  "description": "Mastodon account connection IDs to post from",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / platforms / items / enum
      Previous value: -[
      -  "LINKEDIN",
      -  "YOUTUBE",
      -  "INSTAGRAM",
      -  "FACEBOOK",
      -  "TIKTOK",
      -  "PINTEREST",
      -  "THREADS",
      -  "BLUESKY",
      -  "TWITTER"
      -]New value: +[
      +  "LINKEDIN",
      +  "YOUTUBE",
      +  "INSTAGRAM",
      +  "FACEBOOK",
      +  "TIKTOK",
      +  "PINTEREST",
      +  "THREADS",
      +  "BLUESKY",
      +  "TWITTER",
      +  "MASTODON"
      +]
    • changedInput schema / properties / posts / items / properties / mediaAltTexts / description
      Previous value: -"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"New value: +"Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, Mastodon, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it"
  12. Changed1 schema field changed
    • addedInput schema / properties / posts / items / properties / mediaAltTexts
      Added value: +{
      +  "description": "Alt text per image, in the same order as mediaUrls (max 1000 characters each; use \"\" to skip an image). Sent to X, Bluesky, LinkedIn, Facebook, Instagram and Threads; Pinterest uses the first one (cut to 500). TikTok, YouTube and videos ignore it",
      +  "items": {
      +    "maxLength": 1000,
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  13. Changed11 schema fields changed
    • changedInput schema / properties / facebookConfigs / description
      Previous value: -"Facebook per-page config with post type and video title"New value: +"Facebook per-page config with post type and video title. pageId must match an entry in pageIds"
    • changedInput schema / properties / pageIds / description
      Previous value: -"Facebook page IDs"New value: +"Facebook page account ids from list_accounts (the account id; its pageId value is also accepted). Facebook has no connection-id array"
    • changedInput schema / properties / pinterestConfigs / description
      Previous value: -"Pinterest per-connection config. boardId is required for Pinterest posts"New value: +"Pinterest per-connection config. Each entry needs connectionId + boardId; there is no API to list boards, so ask the user for the board id"
    • changedInput schema / properties / platforms / description
      Previous value: -"Target platforms"New value: +"Target platforms shared by every item. Each needs its connection-id array (pageIds for FACEBOOK)"
    • changedInput schema / properties / posts / description
      Previous value: -"Array of posts to schedule"New value: +"1 to 100 posts to schedule; each is created independently"
    • addedInput schema / properties / posts / items / properties / contentType / description
      Added value: +"TEXT, IMAGE, VIDEO, or CAROUSEL; must match mediaUrls"
    • changedInput schema / properties / posts / items / properties / mediaUrls / description
      Previous value: -"Image or video URLs to attach"New value: +"publicUrl values from upload_media; unstored URLs fail this item"
    • addedInput schema / properties / posts / items / properties / platformTexts / description
      Added value: +"Per-platform caption overrides for this item"
    • changedInput schema / properties / posts / items / properties / scheduledAt / description
      Previous value: -"ISO 8601 schedule time"New value: +"Absolute ISO 8601 instant; a past time publishes immediately"
    • changedInput schema / properties / timezone / description
      Previous value: -"IANA timezone"New value: +"IANA timezone stored with every post for display; does not shift scheduledAt"
    • changedOutput schema / properties / result / description
      Previous value: -"The created scheduled post records with their ids, statuses, and schedule times as returned by the AdaptlyPost API."New value: +"An object with totalScheduled, totalFailed, and results: one { postId, success, isScheduled, scheduledAt, errorMessage } per input item, in input order."
  14. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructive=true, readOnly=false, and openWorld=true, but the description adds meaningful behavioral context: items are processed independently, one bad item fails alone, past scheduledAt values publish immediately, and repeated calls can create duplicates. It also discloses public publishing and requires showing every item plus accounts for confirmation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose, validation step, item failure behavior, platform constraints, confirmation requirement, and duplicate warning are front-loaded and useful. The description is dense and somewhat long for a single paragraph, with some platform details repeated from the schema, but it remains readable and appropriate for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for a complex batch mutation tool: it covers input sharing versus per-item overrides, independent processing and partial failures, validation, platform-specific requirements, draft limitations, confirmation, and duplicate risk. Since an output schema exists, it does not need to explain return formats further, though it helpfully mentions the result shape.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents parameters in detail. The description still adds useful batch-level semantics by explaining which values are shared across all items and which platform configs can be overridden per item, plus limitations such as twitterKeepLinks and linkedinConfigs being unavailable in bulk.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific verb and resource: scheduling up to 100 posts in one call. It also distinguishes the batch operation from create_post and validate_bulk_posts, so an agent can tell when this tool is the correct choice.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing guidance: call validate_bulk_posts first, use create_post for a single post or draft, call list_accounts first, and use list_posts before retrying after errors. It also states that this tool has no draft mode and requires user confirmation before publishing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources