social-media-post — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited social-media-post (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You have access to PostFast MCP tools for social media scheduling and management.
If any PostFast tool call fails with an authentication/401 error, tell the user:
POSTFAST_API_KEY environment variable with the keylist_accounts to see connected social media accounts. Each account has an id, platform, platformUsername, displayName, and a connectionStatus (CONNECTED or DISABLED) with an optional disabledReason. If connectionStatus is DISABLED, the account won't publish until the user reconnects it — warn the user and don't schedule to it.upload_media with the local file path — it handles getting a signed URL, uploading, and returning a key and type (IMAGE or VIDEO).srt or .vtt file the same way. It comes back with type CAPTION; its key goes in controls.youtubeCaptionKey (see YouTube below), never in mediaItems.pdf, .doc, .docx, .ppt or .pptx file the same way. It comes back with type DOCUMENT; its key goes in controls.linkedinAttachmentKey (see LinkedIn below), never in mediaItemscreate_posts with:socialMediaId: account ID from step 1content: the post text/captionscheduledAt: ISO 8601 datetime (required unless status is DRAFT)mediaItems: array of {key, type, sortOrder} from uploaded mediastatus: SCHEDULED (default) or DRAFTfirstComment: optional first comment text, posted automatically after publishing (supported on X, Instagram, Facebook, YouTube, Threads, and TikTok — TikTok: max 1,200 chars)controls: platform-specific settings (see below)DISABLED account — the API rejects it with HTTP 400 socialMediaDisconnected. Saving as DRAFT is still allowed. Check connectionStatus from step 1 first.xRetweetUrl: URL of tweet to retweet (ignores content/media)instagramPublishType: TIMELINE (default), STORY, or REELinstagramTrialReelStrategy: MANUAL or SS_PERFORMANCE — publishes a trial reel, shown only to non-followers until it graduates. MANUAL = the user graduates it in the Instagram app; SS_PERFORMANCE = Instagram graduates it automatically if it performs well. Requires instagramPublishType: REEL and can't be combined with instagramCollaborators (both rejected with HTTP 400 at create time). Omit for a normal reelinstagramPostToGrid: boolean, default true (for Reels)instagramCollaborators: array of usernames to invite as collaboratorsinstagramIsAiGenerated: boolean, default false — adds Instagram's "AI info" label. Covers images, reels, stories and carousels (on a carousel it labels the whole post, not individual slides). Set at creation only; the label can't be added or removed after publishingfacebookContentType: POST (default), REEL, or STORYfacebookReelsCollaborators: array of usernames (for Reels)tiktokPrivacy: deprecated — TikTok videos use the account default privacy (no per-post control) and photos default to public; use tiktokIsDraft for private poststiktokIsDraft: boolean, default falsetiktokAllowComments: boolean, default truetiktokAllowDuet: boolean, default truetiktokAllowStitch: boolean, default truetiktokBrandOrganic: boolean, default falsetiktokBrandContent: boolean, default falsetiktokAutoAddMusic: boolean, default false (let TikTok add a recommended sound — photo/carousel posts only, ignored on videos; mutually exclusive with tiktokMusicSoundId)tiktokIsAigc: boolean, default false (declare the post as AI-generated content — videos and photo posts)tiktokTitle: title for photo posts (max 90 chars; photo posts only) — when set, the full content becomes the description; without it, content auto-splits on the first newline into title + descriptiontiktokMusicSoundId + tiktokMusicSoundName: attach a pre-cleared Commercial Music Library sound to a photo, carousel or video post — find sounds with list_tiktok_sounds (the list rotates daily). On video the sound plays at 50% volume over the video's original audio at 50%, like the TikTok app; there are no volume or trim controls. Mutually exclusive with tiktokAutoAddMusic; not applied when tiktokIsDraft is true. Always set the name alongside the idyoutubeTitle: defaults to first 100 chars of contentyoutubePrivacy: PUBLIC (default), PRIVATE, or UNLISTEDyoutubeTags: array of tag stringsyoutubeCategoryId: YouTube category IDyoutubeIsShort: boolean, default trueyoutubeMadeForKids: boolean, default false (COPPA compliance)youtubeContainsSyntheticMedia: boolean, default false — discloses that the video contains realistic altered or synthetic (AI) content. Sent to YouTube only when true; set at creation onlyyoutubePlaylistId: playlist ID (use list_youtube_playlists to find it)youtubeThumbnailKey: S3 media key for custom video thumbnail (upload via upload_media or get_upload_urls; JPEG/PNG recommended, max 2MB, min 640px wide, 1280x720 ideal; requires phone-verified YouTube channel)youtubeLanguage: the video's language as a BCP-47 code (en, en-GB, es, es-419, fr-CA, pt-BR, zh-Hans, …). Sets both the video language (what is spoken) and the title and description language on YouTube, and is the language of the captions. An unknown code is rejectedyoutubeCaptionKey: the key of an uploaded .srt or .vtt caption file (upload it with upload_media before creating the post), added as the video's caption track in youtubeLanguage, which it requires. One caption track per post. The file must be a timed SRT or WebVTT file in plain UTF-8, max 10MB; a transcript without timings doesn't work. YouTube's automatic captions stay listed separately as "(auto-generated)". If adding the captions fails, the video still publishes without themcreate_posts call, so videos in different languages, each with its own caption file, need one call per videopinterestBoardId: required — use list_pinterest_boards to get the boardIdpinterestLink: destination URL when pin is clickedgbpLocationId: required — use list_gbp_locations to get the locationIdgbpTopicType: STANDARD (default), EVENT, or OFFERgbpCallToActionType: BOOK, ORDER, LEARN_MORE, SIGN_UP, CALL, or SHOPgbpCallToActionUrl: URL for the CTA button (not needed for CALL, ignored for OFFER)gbpEventTitle: title for EVENT/OFFER posts (max 58 chars)gbpEventStartDate: start date (ISO 8601, required for EVENT/OFFER)gbpEventEndDate: end date (ISO 8601, required for EVENT/OFFER)gbpOfferCouponCode: coupon code (OFFER only)gbpOfferRedeemUrl: redemption URL (OFFER only)gbpOfferTerms: terms and conditions (OFFER only)linkedinAttachmentKey: the key of an uploaded PDF, Word or PowerPoint file (upload it with upload_media before creating the post; type DOCUMENT), shown in the post as pages readers swipe throughlinkedinAttachmentTitle: the document's title (default "Document"); set it whenever you attach a documentthreadsTopicTag: the post's Threads topic — one topic, not a list; 1-50 characters, no . or &. Takes precedence over a #hashtag in the content, which then stays plain text. Ignored on other platforms. Like every control it applies to every post in the call, so use separate create_posts calls for Threads posts with different topicslist_posts — filter by platforms (comma-separated), accounts (socialMediaIds, the ids from list_accounts, max 100), statuses (DRAFT, SCHEDULED, PUBLISHED, FAILED), from/to dates, with pagination (page, limit up to 50). Failed or missed posts include a lastError with a code — e.g. MISSED_DISCONNECTED (the account was disconnected when the post was due) or MISSED_NOT_PUBLISHED (missed its slot by more than the 2h grace window). Each post also carries controls — threadsTopicTag, instagramPublishType, facebookContentType, tiktokIsDraft, youtubePrivacy, each null when unset. Read only the field for the post's own platform (its account's platform in list_accounts): posts created through the API store every platform's defaults, so the others can be non-nullget_post_analytics — fetch published posts with performance metrics. Requires startDate and endDate (ISO 8601). Optional filters: platforms, socialMediaIds. Returns impressions, reach, likes, comments, shares, totalInteractions, plus an extras object with platform-specific metrics. Supported: Instagram, Facebook, TikTok, Threads, YouTube, LinkedIn (company pages), Pinterest (Business accounts). Pinterest extras include pin_clicks, outbound_clicks, saves_90d, save_rate_90d; video pins also surface mrc_views, views_10s, avg_watch_time, v50_watch_time, video_starts, quartile_95_views. Video posts also include normalized watch-time on latestMetric: avgWatchTimeSeconds, totalWatchTimeSeconds, videoViews (Facebook, Instagram Reels, YouTube, Pinterest, LinkedIn company pages, TikTok); Instagram posts also include saveRate on latestMetric (saves / reach as a percentage, rounded to 2 decimals; feed posts, reels, and carousels), and Instagram Reels additionally include reelsSkipRate (percentage of viewers who skipped the reel in the first 3 seconds, rounded to 2 decimals; may be absent on low-view reels or until metrics refresh); TikTok also exposes total_time_watched, average_time_watched, and full_video_watched_rate in metric.extras. Note: LinkedIn personal accounts are excluded; Pinterest saves are reported as a rolling 90-day window because Pinterest's API does not expose lifetime save totals (all other Pinterest metrics are lifetime); latestMetric is null if metrics haven't been fetched yet; metric values are strings (bigint). Keep date ranges reasonable as there's no pagination.get_follower_history — daily follower-count snapshots for one account (socialMediaId), plus currentFollowerCount and a signed delta over the range. Optional from/to (ISO 8601); defaults to the last 90 days, capped at 365. Tracking is forward-only — trackingStartedAt marks when recording began, with no data before it; counts are strings (bigint). Coverage: Facebook Pages, Instagram, YouTube, Pinterest, Threads, Bluesky, Telegram, LinkedIn company pages, and TikTok (not X or personal Facebook)delete_post with the post ID, or delete_posts with up to 100 post IDs in one call (it returns deletedIds and notFoundIds). Both remove posts from PostFast only: an already-published post stays live on the platformgenerate_connect_link — creates a secure URL to share with clients/collaborators to connect their accounts. Set expiryDays (1-30) and optionally sendEmail with an email addresslist_pinterest_boards — get board IDs before creating Pinterest postslist_youtube_playlists — get playlist IDs for adding videos to playlistslist_gbp_locations — get location IDs before creating Google Business Profile postslist_accounts shows an account as DISABLED, tell the user to reconnect it before scheduling — scheduled posts to disconnected accounts are rejected, and posts already due get marked missed.create_posts call (up to 15).pinterestBoardId is required.gbpLocationId is required.firstComment feature is useful for adding hashtags on Instagram without cluttering the caption.instagramIsAiGenerated, youtubeContainsSyntheticMedia, or tiktokIsAigc. All three are set at creation time only — there's no way to add or remove the label after publishing, so ask before scheduling. The other platforms expose no AI flag.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.