POST/social-posts
Creates and schedules one or more social posts (up to 15 per request).
pf-api-keyRate limit: 350 requests per day, 150 per minuteMaximum 250 MB per video and 10 MB per image.Disabled accounts
If a post's socialMediaId points to an account whose connectionStatus is DISABLED, scheduling it returns 400 Bad Request. You can still save it as a draft (status: DRAFT). Check connectionStatus via GET /social-media/my-social-accounts first.
X (Twitter) per-account daily cap
PostFast caps X API posts per account per day: 6 on Starter, Creator, and Growth; 9 on Pro and Enterprise. An organization-wide daily X cap also applies. These are separate from the request rate limits.
Daily posting limits
Each platform has its own per-account daily posting limit, resetting at midnight UTC. See the fair usage policy at postfa.st/fair-usage for details.
Geo controls are shared across every post in a request
The controls object is applied to every post in the posts[] array. Because each geo field is platform-specific and validated per post, batch by platform when using geotags or country limits: send Facebook posts in one request and Instagram posts in another, rather than mixing platforms whose controls do not apply to the other.
Resolve place IDs with GET /social-media/search-places; the same id works as both facebookPlaceId and instagramLocationId.
Request body
postsarrayrequiredArray of post objects (1-15 per request).
contentstringrequiredText content of the post.
mediaItemsarrayoptionalMedia attached to the post.
keystringrequiredS3 object key from /file/get-signed-upload-urls.
typestringrequiredWhether the item is an image or a video.
IMAGEVIDEOsortOrdernumberrequiredOrdering of the media items.
coverTimestampstringoptionalMillisecond timestamp used as the video cover (e.g. 5000). Supported on TikTok, Instagram Reels, and Pinterest video pins; not supported on Facebook.
coverImageKeystringoptionalS3 key of a custom video cover/thumbnail. Takes priority over coverTimestamp where supported (Instagram Reels JPEG max 8MB; Facebook Reels max 10MB; Pinterest JPEG/PNG; YouTube uses youtubeThumbnailKey; not supported on TikTok).
scheduledAtISO 8601Required (unless DRAFT)UTC date-time, e.g. YYYY-MM-DDTHH:mm:ss.sssZ. Must be in the future, within 1 year.
socialMediaIdstring (UUID)requiredTarget account id from /social-media/my-social-accounts.
firstCommentstringoptionalAutomatic first comment, posted ~10s after publish (up to 3 attempts). Supported on X, Instagram, Facebook, YouTube, Threads, and TikTok. On TikTok the cap is 150 chars and comments must be enabled on the post; a TikTok account that can't post comments returns firstComment.tiktok.notSupported. See the first-comment limits table below.
statusstringoptionaldefault SCHEDULEDWhether the post is scheduled or saved as a draft.
DRAFTSCHEDULEDapprovalStatusstringoptionaldefault APPROVEDAPPROVED publishes; PENDING_APPROVAL holds for review.
APPROVEDPENDING_APPROVALcontrolsobjectoptionalPlatform-specific settings (see the controls matrix below).
Controls (platform-specific)
Optional controls object. Each field applies only to its platform; PostFast validates which controls are valid for the target account.
X (Twitter)
xRetweetUrlstringoptionalURL of a tweet to retweet without changes. Content and media are ignored when set. Accepts x.com, twitter.com, mobile.twitter.com.
instagramPublishTypestringoptionaldefault TIMELINEWhere the media is published.
TIMELINESTORYREELinstagramPostToGridbooleanoptionaldefault trueAlso post to the profile grid.
instagramCollaboratorsstring[]optionalInstagram usernames invited as collaborators.
instagramTrialReelStrategystringoptionalPublish the reel as a trial (non-followers only). Requires instagramPublishType: REEL; cannot combine with collaborators.
MANUALSS_PERFORMANCEinstagramLocationIdstringoptionalGeotag the post with a physical place. Same numeric ID returned by /social-media/search-places (the value also used for facebookPlaceId). Works on a single image, video, reel, or story - not on carousels (2+ media items).
instagramLocationNamestringoptionalOptional display label for the location. Stored for your portal/UI; never sent to Meta.
instagramLocationId works on a single image, video, reel, or story - not on carousels (2 or more media items).
facebookContentTypestringoptionaldefault POSTPOST = up to 10 photos or 1 video; REEL = 1 video; STORY = 1 image or video.
POSTREELSTORYfacebookReelsCollaboratorsstring[]optionalFacebook usernames invited to a Reel collaboration.
facebookPlaceIdstringoptionalGeotag the post with a physical place. Numeric Facebook Page ID with location data, resolved via /social-media/search-places. Feed posts only (text/photo/carousel) - not Reels, Stories, or video posts.
facebookPlaceNamestringoptionalOptional display label for the place. Stored for your portal/UI; never sent to Meta.
facebookTargetCountriesstring[]optionalRestrict who can see the post by country. Array of ISO 3166-1 alpha-2 codes (case-insensitive), max 25, e.g. ["BG", "DE", "AT"]. Feed posts only. Can be combined with a geotag.
Geotag (facebookPlaceId) and country limit (facebookTargetCountries) both apply to feed posts only - not Reels, Stories, or video posts.
facebookTargetCountries is audience gating, not a hint: only people in the listed countries can see the post, and it is hidden from anyone not logged in to Facebook, so total reach drops.
TikTok
tiktokTitlestringoptionalCarousel title (max 90 chars, photo carousels only). When set, content becomes the description.
tiktokPrivacystringoptionaldefault PUBLICDeprecated. On TikTok, videos use the account's default privacy (no per-post control); photos default to public. To publish privately, save a draft with tiktokIsDraft: true. Still accepted for backward compatibility.
PUBLICMUTUAL_FRIENDSFOLLOWER_OF_CREATORONLY_MEtiktokIsDraftbooleanoptionaldefault falseSave to TikTok drafts instead of publishing.
tiktokAllowCommentsbooleanoptionaldefault trueAllow comments.
tiktokAllowDuetbooleanoptionaldefault trueAllow duets.
tiktokAllowStitchbooleanoptionaldefault trueAllow stitches.
tiktokBrandOrganicbooleanoptionaldefault falseYour own brand promotion.
tiktokBrandContentbooleanoptionaldefault falsePaid partnership / branded content.
tiktokAutoAddMusicbooleanoptionaldefault falseLet TikTok add music automatically.
tiktokIsAigcbooleanoptionaldefault falseDisclose AI-generated content.
YouTube
youtubeTitlestringoptionalVideo title (defaults to first 100 chars of content).
youtubePrivacystringoptionaldefault PUBLICVisibility of the video.
PRIVATEPUBLICUNLISTEDyoutubeTagsstring[]optionalVideo tags.
youtubeCategoryIdstringoptionalYouTube category id.
youtubeIsShortbooleanoptionaldefault truePublish as a Short.
youtubeMadeForKidsbooleanoptionaldefault falseCOPPA made-for-kids flag.
youtubePlaylistIdstringoptionalPlaylist to add the video to after publishing (from /youtube-playlists). The playlist must belong to the authenticated channel; the video still publishes if the playlist addition fails.
youtubeThumbnailKeystringoptionalCustom thumbnail media key (JPEG/PNG recommended; GIF/BMP/WebP also allowed; max 2MB; 1280x720). Requires a phone-verified channel; the video still publishes if the thumbnail upload fails.
pinterestBoardIdstringRequired for PinterestBoard to publish the pin to (from /pinterest-boards).
pinterestLinkstringoptionalDestination URL when users click the pin.
Content parsing: first line becomes the pin title (max 100 chars); the rest becomes the description (max 800).
Carousel pins support 2-5 static images (no video).
linkedinAttachmentKeystringRequired for documentsS3 key from /file/get-signed-upload-urls for a PDF/DOC/DOCX/PPT/PPTX (max 60MB). Cannot mix with mediaItems.
linkedinAttachmentTitlestringoptionaldefault DocumentDisplay title for the document.
Google Business Profile
gbpLocationIdstringRequired for GBPLocation resource name (from /gbp-locations).
gbpTopicTypestringoptionaldefault STANDARDPost type.
STANDARDEVENTOFFERgbpCallToActionTypestringoptionalCTA button.
BOOKORDERSHOPLEARN_MORESIGN_UPCALLgbpCallToActionUrlstringoptionalDestination URL for the CTA button. Used when a CTA type other than CALL is set.
gbpEventTitlestringoptionalTitle for EVENT/OFFER posts (max 58 chars).
gbpEventStartDateISO 8601Required for EVENT/OFFERStart of the event or offer.
gbpEventEndDateISO 8601Required for EVENT/OFFEREnd of the event or offer.
gbpOfferCouponCodestringoptionalCoupon code (OFFER only).
gbpOfferRedeemUrlstringoptionalRedemption URL (OFFER only).
gbpOfferTermsstringoptionalTerms and conditions (OFFER only).
1 image only (JPEG/PNG), no video or carousel. Content limit 1500 chars.
Standard posts are visible for 6 months; Event and Offer posts stay until their end date.
The call-to-action button is ignored on OFFER posts.
Platform character limits
| Platform | `content` cap | Notes |
|---|---|---|
| 63,206 | ||
| X (Twitter) | 4,000 | Premium default; free-tier accounts are capped at 280 by X. |
| 2,200 | ||
| 3,000 | ||
| TikTok | 4,000 / 2,200 | Photo carousels: 4,000. Narrows to 2,200 if any media item is a VIDEO. See also tiktokTitle (max 90, photo carousels only). |
| YouTube | 5,000 | < and > are not allowed in titles or descriptions. |
| BlueSky | 300 | |
| Threads | 500 | |
| 900 | First line is the pin title (max 100); the remaining 800 chars become the description. | |
| Telegram | 4,096 | |
| Google Business Profile | 1,500 |
Exceeding a cap returns 400 Bad Request with a contentLength.<platform> error key.
First-comment limits
| Platform | `firstComment` cap |
|---|---|
| 2,200 | |
| 8,000 | |
| YouTube | 10,000 |
| Threads | 500 |
| X (Twitter) | 4,000 (Premium); 280 (free tier) |
| TikTok | 150 |
On TikTok, firstComment requires comments enabled on the post (tiktokAllowComments); if comments are disabled the comment is silently skipped at publish time, and a TikTok account that can't post comments returns firstComment.tiktok.notSupported. firstComment is not supported on LinkedIn, Pinterest, BlueSky, or Google Business Profile and returns a validation error.
Geo controls validation errors
| Situation | Error |
|---|---|
| Geo field sent for the wrong platform | facebookPlaceId.notSupported / instagramLocationId.notSupported / facebookTargetCountries.notSupported |
| Geotag on a Facebook Reel or Story | facebookPlaceId.contentType.notSupported |
| Geotag on a Facebook video post | facebookPlaceId.video.notSupported |
| Geotag on an Instagram carousel | instagramLocationId.carousel.notSupported |
| Country limit on a Facebook Reel or Story | facebookTargetCountries.contentType.notSupported |
| More than 25 countries | facebookTargetCountries.tooMany |
| Invalid country code (not a real ISO 3166-1 alpha-2) | 400 - rejected by input validation; the message lists the allowed values |
| Non-numeric place/location ID | facebookPlaceId.invalidId / instagramLocationId.invalidId |
The facebookPlaceName and instagramLocationName fields are optional, display-only, and stored so the place name shows in your portal. They are never sent to Meta - only the IDs and country codes are.
Response
201 Created An object with the ids of the created posts.