Skip to main content
Glama

Create Post

create_post
Destructive

Create one post on the user's own connected social accounts. saveAsDraft saves a DRAFT and publishes nothing; a scheduledAt sent with it becomes the draft's planned date, which publish_draft later schedules. Without saveAsDraft, a future scheduledAt schedules the post; otherwise it publishes now. Before publishing or scheduling, show the user the final text, media, accounts and time (or repeat schedule) and get their confirmation; a draft needs no confirmation. Account ids come from list_accounts (pass them as accountIds, or as platforms plus the per-platform arrays) and mediaUrls from upload_media. Platform-specific options (TikTok privacy, Pinterest board, LinkedIn document or reshare, Google Business event or offer, Tumblr tags, Instagram user tags, Facebook link carousel, first comments, threads of replies, recurrence) are described on each field. To find every problem before creating anything, call validate_post with the same input first. Publishing runs per platform in the background, so the response ({ postId, queuedPlatforms, isScheduled, scheduledAt }) is not the outcome; check list_post_results. Each call creates a separate post, so after an error or timeout check list_posts before trying again. Use update_post or publish_draft for an existing post and bulk_schedule_posts for many posts.

Input Schema

NameRequiredDescriptionDefault
textNoDefault post text shared across platforms. On LinkedIn, mention a company page with @[Page Name](urn:li:organization:<id>), using the page name exactly as LinkedIn shows it
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 the post for display (e.g. "America/New_York"); it does not shift scheduledAtUTC
mediaUrlsNoMedia URLs to attach. Use publicUrl values from upload_media or get_upload_urls; the same publicUrl may be reused across posts. Do not reuse mediaUrls read back from a published post, which may be expiring platform links
platformsNoTarget platforms (e.g. ["LINKEDIN", "TWITTER"]). Each one needs its matching connection-id array (pageIds for FACEBOOK, googleBusinessConnectionIds for GOOGLE_BUSINESS) filled with ids from list_accounts. Optional when accountIds is sent
accountIdsNoAccount ids (or Facebook pageIds) from list_accounts to post to. AdaptlyPost adds each account's platform to platforms and its id to the matching connection-id array, so you can send these instead of platforms and the per-platform arrays, or alongside them. An id not connected to the workspace fails with 400
recurrenceNoRepeat the post on a schedule the user asked for, and confirm that schedule with them first. Needs a future scheduledAt, which becomes the first post and sets the time of day in timezone. Cannot be combined with saveAsDraft or TIKTOK. Missed slots, for example while paused, are skipped and never published late. The user can pause or stop the series at any time with pause_recurring_post or delete_recurring_post; list_recurring_posts shows it
contentTypeYesContent type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls. 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. DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs
saveAsDraftNoSave as DRAFT instead of publishing or scheduling; publish later with publish_draft. A scheduledAt sent with it is stored as the draft's planned date, and publish_draft schedules the draft for that date
scheduledAtNoAbsolute ISO 8601 instant to schedule (e.g. "2026-03-15T10:00:00Z"). Omit to post immediately; a past time also posts immediately. With saveAsDraft it is the draft's planned date instead: nothing is scheduled, and publish_draft without a date later schedules the draft for it
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
thumbnailUrlNoVideo thumbnail as an https URL or an image data URI, used on every platform that takes one unless platformThumbnails overrides it
firstCommentsNoA 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
mediaAltTextsNoAlt 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
platformTextsNoPer-platform caption overrides
threadRepliesNoTurns 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
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
linkedinConfigsNoLinkedIn per-connection config: documentTitle names a DOCUMENT post, reshareOf reshares another LinkedIn post with the text as commentary. connectionId must match an entry in linkedinConnectionIds
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
twitterKeepLinksNoKeep links in the X text clickable. X charges over 10 times more for a post with a link, so by default every link in X text is broken (example.com becomes example. com). Only AppSumo lifetime deals can turn this on, and a kept link costs 20 credits instead of 2. true on any other plan is refused with 400; it is ignored when the X text has no link
platformThumbnailsNoA 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
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
platformAspectRatiosNoReframe 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
threadsConnectionIdsNoThreads account connection IDs to post from
thumbnailTimestampMsNoVideo frame timestamp (ms) to use as the thumbnail, used by INSTAGRAM, PINTEREST and TIKTOK unless platformThumbnails overrides it
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 postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt, plus recurringPostId when recurrence was sent. Publishing is asynchronous: check list_post_results for outcomes.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / saveAsDraft / description
      Previous value: -"Save as DRAFT instead of publishing or scheduling; publish later with publish_draft"New value: +"Save as DRAFT instead of publishing or scheduling; publish later with publish_draft. A scheduledAt sent with it is stored as the draft's planned date, and publish_draft schedules the draft for that date"
    • changedInput schema / properties / scheduledAt / description
      Previous value: -"Absolute ISO 8601 instant to schedule (e.g. \"2026-03-15T10:00:00Z\"). Omit to post immediately; a past time also posts immediately"New value: +"Absolute ISO 8601 instant to schedule (e.g. \"2026-03-15T10:00:00Z\"). Omit to post immediately; a past time also posts immediately. With saveAsDraft it is the draft's planned date instead: nothing is scheduled, and publish_draft without a date later schedules the draft for it"
  2. 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"
  3. Changed24 schema fields changed
    • addedInput schema / properties / accountIds
      Added value: +{
      +  "description": "Account ids (or Facebook pageIds) from list_accounts to post to. AdaptlyPost adds each account's platform to platforms and its id to the matching connection-id array, so you can send these instead of platforms and the per-platform arrays, or alongside them. An id not connected to the workspace fails with 400",
      +  "items": {
      +    "type": "string"
      +  },
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / contentType / description
      Previous value: -"Content type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls. 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. DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"New value: +"Content type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls. 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. DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"
    • 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"
    • addedInput schema / 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 / 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 / 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 / firstComments / items / properties / platform / enum
      Previous value: -[
      -  "LINKEDIN",
      -  "TWITTER",
      -  "THREADS",
      -  "BLUESKY",
      -  "MASTODON",
      -  "YOUTUBE"
      -]New value: +[
      +  "LINKEDIN",
      +  "TWITTER",
      +  "THREADS",
      +  "BLUESKY",
      +  "MASTODON",
      +  "YOUTUBE",
      +  "FACEBOOK",
      +  "INSTAGRAM"
      +]
    • 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"
    • addedInput schema / 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 / 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 / linkedinConfigs / description
      Previous value: -"LinkedIn per-connection config: documentTitle names a DOCUMENT post. connectionId must match an entry in linkedinConnectionIds"New value: +"LinkedIn per-connection config: documentTitle names a DOCUMENT post, reshareOf reshares another LinkedIn post with the text as commentary. connectionId must match an entry in linkedinConnectionIds"
    • addedInput schema / properties / linkedinConfigs / items / properties / reshareOf
      Added value: +{
      +  "description": "Reshare this LinkedIn post from the account, with the post text as the commentary. Takes a urn:li:share: or urn:li:ugcPost: URN, such as the platformPostId from list_post_results, or a LinkedIn post link of the form https://www.linkedin.com/feed/update/<urn>, which is also the link inside a post's Embed code. urn:li:activity: links are refused because LinkedIn cannot reshare them through its API. Media on the post is not attached on this account",
      +  "maxLength": 500,
      +  "type": "string"
      +}
    • changedInput schema / 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 / 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 / platformThumbnails / items / properties / platform / enum
      Previous value: -[
      -  "YOUTUBE",
      -  "FACEBOOK",
      -  "LINKEDIN",
      -  "INSTAGRAM",
      -  "PINTEREST",
      -  "TIKTOK"
      -]New value: +[
      +  "YOUTUBE",
      +  "FACEBOOK",
      +  "LINKEDIN",
      +  "TELEGRAM",
      +  "INSTAGRAM",
      +  "PINTEREST",
      +  "TIKTOK"
      +]
    • changedInput schema / properties / platforms / description
      Previous value: -"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"]). Each one needs its matching connection-id array (pageIds for FACEBOOK, googleBusinessConnectionIds for GOOGLE_BUSINESS) filled with ids from list_accounts"New value: +"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"]). Each one needs its matching connection-id array (pageIds for FACEBOOK, googleBusinessConnectionIds for GOOGLE_BUSINESS) filled with ids from list_accounts. Optional when accountIds is sent"
    • 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"
      +]
    • addedInput schema / properties / platforms / minItems
      Added value: +1
    • 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 / 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 / tumblrConfigs
      Added value: +{
      +  "description": "Tumblr per-blog config: tags, a title and a source link. connectionId must match an entry in tumblrConnectionIds",
      +  "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 / tumblrConnectionIds
      Added value: +{
      +  "description": "Tumblr blog account ids from list_accounts to post to",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedInput schema / 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"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "platforms",
      -  "contentType"
      -]New value: +[
      +  "contentType"
      +]
  4. Changed2 schema fields changed
    • changedInput schema / properties / recurrence / description
      Previous value: -"Repeat the post on a schedule. Needs a future scheduledAt, which becomes the first post and sets the time of day in timezone. Cannot be combined with saveAsDraft or TIKTOK. Missed slots, for example while paused, are skipped and never published late. X and LinkedIn reject identical text, so use spintax such as {Hi|Hello} to vary each post. Manage the series with list_recurring_posts, pause_recurring_post, resume_recurring_post and delete_recurring_post"New value: +"Repeat the post on a schedule the user asked for, and confirm that schedule with them first. Needs a future scheduledAt, which becomes the first post and sets the time of day in timezone. Cannot be combined with saveAsDraft or TIKTOK. Missed slots, for example while paused, are skipped and never published late. The user can pause or stop the series at any time with pause_recurring_post or delete_recurring_post; list_recurring_posts shows it"
    • changedInput schema / properties / recurrence / properties / maxOccurrences / description
      Previous value: -"Total number of posts the series publishes, 2 to 365. Cannot be combined with endsOn; omit both to repeat until paused or deleted"New value: +"Total number of posts the series publishes, 2 to 365. Cannot be combined with endsOn; omit both to repeat until the user pauses or deletes the series"
  5. Changed3 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 / 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 / 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"
      +}
  6. 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 / 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 / pinterestConfigs / items / required
      Previous value: -[
      -  "connectionId",
      -  "boardId"
      -]New value: +[
      +  "connectionId"
      +]
  7. Changed26 schema fields changed
    • changedInput schema / properties / contentType / description
      Previous value: -"Content type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls (CAROUSEL needs several). DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"New value: +"Content type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls. 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. DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"
    • 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"
    • changedInput schema / 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 / 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 / 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 / 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 / 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": {
      +    "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/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 / 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"
    • addedInput schema / 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 / 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 / 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 / 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 / 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 / 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 / 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 / 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 / platforms / description
      Previous value: -"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"]). Each one needs its matching connection-id array (pageIds for FACEBOOK) filled with ids from list_accounts"New value: +"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"]). Each one needs its matching connection-id array (pageIds for FACEBOOK, googleBusinessConnectionIds for GOOGLE_BUSINESS) filled with ids from list_accounts"
    • 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 / recurrence / properties / frequency / description
      Previous value: -"How often the post repeats: DAILY, WEEKLY, or MONTHLY"New value: +"How often the post repeats: DAILY, WEEKLY, MONTHLY or YEARLY. YEARLY repeats on the same date; a series started on February 29 posts on February 28 in other years"
    • changedInput schema / properties / recurrence / properties / frequency / enum
      Previous value: -[
      -  "DAILY",
      -  "WEEKLY",
      -  "MONTHLY"
      -]New value: +[
      +  "DAILY",
      +  "WEEKLY",
      +  "MONTHLY",
      +  "YEARLY"
      +]
    • changedInput schema / properties / recurrence / properties / interval / description
      Previous value: -"Repeat every N days, weeks or months, 1 to 30 (default 1)"New value: +"Repeat every N days, weeks, months or years, 1 to 30 (default 1)"
    • changedInput schema / properties / text / description
      Previous value: -"Default post text shared across platforms"New value: +"Default post text shared across platforms. 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 / thumbnailTimestampMs / description
      Previous value: -"Generate thumbnail from video at this timestamp (milliseconds)"New value: +"Video frame timestamp (ms) to use as the thumbnail, used by INSTAGRAM, PINTEREST and TIKTOK unless platformThumbnails overrides it"
    • changedInput schema / properties / thumbnailUrl / description
      Previous value: -"Custom thumbnail image URL for video posts"New value: +"Video thumbnail as an https URL or an image data URI, used on every platform that takes one unless platformThumbnails overrides it"
    • addedInput schema / properties / twitterKeepLinks
      Added value: +{
      +  "description": "Keep links in the X text clickable. X charges over 10 times more for a post with a link, so by default every link in X text is broken (example.com becomes example. com). Only AppSumo lifetime deals can turn this on, and a kept link costs 20 credits instead of 2. true on any other plan is refused with 400; it is ignored when the X text has no link",
      +  "type": "boolean"
      +}
  8. 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#"
  9. Changed4 schema fields changed
    • changedInput schema / properties / facebookConfigs / items / properties / postType / description
      Previous value: -"Facebook post type — FEED, REEL, or STORY"New 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"
    • changedInput schema / properties / instagramConfigs / items / properties / postType / description
      Previous value: -"Instagram post type — FEED, REEL, or STORY"New 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"
    • addedInput schema / properties / recurrence / properties / weekdays / maxItems
      Added value: +7
    • 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"
  10. 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"
      +}
  11. 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"
      +}
  12. Changed2 schema fields changed
    • addedInput schema / properties / recurrence
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Repeat the post on a schedule. Needs a future scheduledAt, which becomes the first post and sets the time of day in timezone. Cannot be combined with saveAsDraft or TIKTOK. Missed slots, for example while paused, are skipped and never published late. X and LinkedIn reject identical text, so use spintax such as {Hi|Hello} to vary each post. Manage the series with list_recurring_posts, pause_recurring_post, resume_recurring_post and delete_recurring_post",
      +  "properties": {
      +    "endsOn": {
      +      "description": "Last day an occurrence may go out on, as YYYY-MM-DD (inclusive). Must be on or after the day of the first post. Cannot be combined with maxOccurrences",
      +      "type": "string"
      +    },
      +    "frequency": {
      +      "description": "How often the post repeats: DAILY, WEEKLY, or MONTHLY",
      +      "enum": [
      +        "DAILY",
      +        "WEEKLY",
      +        "MONTHLY"
      +      ],
      +      "type": "string"
      +    },
      +    "interval": {
      +      "description": "Repeat every N days, weeks or months, 1 to 30 (default 1)",
      +      "maximum": 30,
      +      "minimum": 1,
      +      "type": "integer"
      +    },
      +    "maxOccurrences": {
      +      "description": "Total number of posts the series publishes, 2 to 365. Cannot be combined with endsOn; omit both to repeat until paused or deleted",
      +      "maximum": 365,
      +      "minimum": 2,
      +      "type": "integer"
      +    },
      +    "weekdays": {
      +      "description": "WEEKLY only: the weekdays it goes out on (e.g. [\"MONDAY\", \"THURSDAY\"]). The weekday of scheduledAt is always included",
      +      "items": {
      +        "enum": [
      +          "MONDAY",
      +          "TUESDAY",
      +          "WEDNESDAY",
      +          "THURSDAY",
      +          "FRIDAY",
      +          "SATURDAY",
      +          "SUNDAY"
      +        ],
      +        "type": "string"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "required": [
      +    "frequency"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / properties / result / description
      Previous value: -"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt. Publishing is asynchronous: check list_post_results for outcomes."New value: +"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt, plus recurringPostId when recurrence was sent. Publishing is asynchronous: check list_post_results for outcomes."
  13. Changed3 schema fields changed
    • changedInput schema / properties / contentType / description
      Previous value: -"Content type: TEXT, IMAGE, VIDEO, or CAROUSEL. Must match mediaUrls (CAROUSEL needs several)"New value: +"Content type: TEXT, IMAGE, VIDEO, CAROUSEL, or DOCUMENT. Must match mediaUrls (CAROUSEL needs several). DOCUMENT publishes one PDF, PPT, PPTX, DOC or DOCX file (max 100 MB, 300 pages) as a LinkedIn document post and is LinkedIn only: put exactly that one file in mediaUrls, target only LINKEDIN, and set the title with linkedinConfigs"
    • changedInput schema / properties / contentType / enum
      Previous value: -[
      -  "TEXT",
      -  "IMAGE",
      -  "VIDEO",
      -  "CAROUSEL"
      -]New value: +[
      +  "TEXT",
      +  "IMAGE",
      +  "VIDEO",
      +  "CAROUSEL",
      +  "DOCUMENT"
      +]
    • addedInput schema / properties / linkedinConfigs
      Added value: +{
      +  "description": "LinkedIn per-connection config: documentTitle names a DOCUMENT post. connectionId must match an entry in linkedinConnectionIds",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "connectionId": {
      +        "description": "LinkedIn connection ID from list_accounts",
      +        "type": "string"
      +      },
      +      "documentTitle": {
      +        "description": "Title LinkedIn shows on a DOCUMENT post (max 100 chars). Defaults to the file name; ignored for other content types",
      +        "maxLength": 100,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "connectionId"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  14. Changed1 schema field changed
    • changedInput schema / properties / mediaUrls / description
      Previous value: -"Media URLs to attach. Use publicUrl values from upload_media or get_upload_urls"New value: +"Media URLs to attach. Use publicUrl values from upload_media or get_upload_urls; the same publicUrl may be reused across posts. Do not reuse mediaUrls read back from a published post, which may be expiring platform links"
  15. 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 / 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"
    • 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"
      +]
  16. Changed1 schema field changed
    • addedInput schema / 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"
      +}
  17. Changed9 schema fields changed
    • changedInput schema / properties / contentType / description
      Previous value: -"Content type: TEXT, IMAGE, VIDEO, or CAROUSEL"New value: +"Content type: TEXT, IMAGE, VIDEO, or CAROUSEL. Must match mediaUrls (CAROUSEL needs several)"
    • 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 (e.g. [\"LINKEDIN\", \"TWITTER\"])"New value: +"Target platforms (e.g. [\"LINKEDIN\", \"TWITTER\"]). Each one needs its matching connection-id array (pageIds for FACEBOOK) filled with ids from list_accounts"
    • changedInput schema / properties / saveAsDraft / description
      Previous value: -"Save as draft instead of publishing"New value: +"Save as DRAFT instead of publishing or scheduling; publish later with publish_draft"
    • changedInput schema / properties / scheduledAt / description
      Previous value: -"ISO 8601 datetime to schedule (e.g. \"2026-03-15T10:00:00Z\"). Omit to post immediately"New value: +"Absolute ISO 8601 instant to schedule (e.g. \"2026-03-15T10:00:00Z\"). Omit to post immediately; a past time also posts immediately"
    • changedInput schema / properties / timezone / description
      Previous value: -"IANA timezone (e.g. \"America/New_York\")"New value: +"IANA timezone stored with the post for display (e.g. \"America/New_York\"); it does not shift scheduledAt"
    • changedOutput schema / properties / result / description
      Previous value: -"The created post record including its id, status, and scheduled time as returned by the AdaptlyPost API."New value: +"An object with postId, queuedPlatforms (platforms whose publishing job was queued; empty for scheduled posts and drafts), skippedPlatforms, isScheduled, and scheduledAt. Publishing is asynchronous: check list_post_results for outcomes."
  18. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare destructiveHint and openWorldHint but say nothing operational; the description adds the crucial non-obvious traits: publishing runs per platform in the background so the response is not the outcome (check list_post_results), each call creates a separate post so check list_posts after an error or timeout before retrying, and confirmation must precede any live or scheduled publish. That is exactly the idempotency and confirmation context an agent needs.

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?

Dense but front-loaded: purpose, then draft-vs-schedule semantics, then confirmation, then inputs, then validation and retry guidance. For a 40-parameter tool this length is largely earned, though a few clauses (e.g. the pointer that platform options are 'described on each field') are meta-filler.

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?

Given 40 parameters, nested configs and an output schema, the description covers everything an agent needs to act correctly: prerequisites (list_accounts, upload_media), pre-flight validation, confirmation policy, async outcome handling, retry safety, and sibling routing. Return values are echoed briefly rather than needing explanation, which is fine since the output schema exists.

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% and per-field docs are extensive, so the description only needs to add cross-parameter meaning — which it does by explaining that accountIds can substitute for platforms plus the per-platform arrays, and by spelling out the scheduledAt/saveAsDraft interaction (draft planned date consumed later by publish_draft). Remaining detail is delegated to the schema, so it stops short of 5.

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?

Opens with a specific verb and resource ('Create one post on the user's own connected social accounts') and immediately scopes the tool to a single post, distinguishing it from publish_draft, update_post and bulk_schedule_posts by name. An agent can tell exactly which creation path this is.

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?

Explicit when-to-use branches: saveAsDraft vs future scheduledAt vs immediate publish; validate_post first to surface all problems; update_post/publish_draft/bulk_schedule_posts for the alternatives. It also states a required human-confirmation workflow before publishing or scheduling and that drafts need none.

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