1. Overview
A Facebook post goes to one Facebook Page. SocialAPI picks the format from themedia you send: no media gives a text or link post, one image a photo post, one video a video post, and 2 to 10 images a multi-photo album. Two richer formats are opt-in with platform_data.content_type: "reel" publishes a Reel, and "stories" publishes a 24-hour Story. Every format is described below.
2. Supported media
The format follows the
media you pass:
mediais empty: a text or link post.mediahas one entry: a photo or a video, by the file extension.mediahas 2 to 10 entries: a multi-photo album.
content_type in the target’s platform_data to "reel" (one vertical video) or "stories" (one photo or video), and that intent takes precedence over the rules above. The value is case-insensitive; any other value publishes a standard feed post and returns a warning naming it.
Text limit: 63,206 characters. More returns 400 publishing.validation_failed.
File limits for media you upload to SocialAPI (source_type: "media_id"): images must be JPEG, PNG, GIF, or WebP and at most 10 MB. Videos must be MP4, QuickTime, or AVI, at most 4 GB, and at most 240 minutes. A file outside these limits fails validation with 400 publishing.validation_failed. A url item is not checked in advance.
Multi-photo album rules:
- 2 to 10 photos per post. Passing more than 10 entries returns a validation error.
- Images only. Mixing images and videos in the same album is rejected with a validation error. Facebook’s Graph API does not support mixed-media albums; publish separate posts.
- If publishing the album fails, no partial post appears on the Page, and you can retry the whole post.
- For best rendering, use consistent 1,080 by 1,080 px (1:1) images.
3. Create post
UsePOST /v1/posts with targets targeting a Facebook Page account. The text field becomes the post message.
pending to publishing, then to published or failed. Poll GET /v1/posts/{pid} or subscribe to the post.published, post.partial, and post.failed webhook events. Publishing or scheduling costs 1 post credit; a draft is free (see Plans and credits).
Platform data fields
Send these keys flat in the target’splatform_data (targets[].platform_data), or in platform_data.facebook on the post, which applies them to every Facebook target. When both set the same key, the target’s value wins. Which keys apply depends on the content type, shown in the “Applies to” column.
SocialAPI forwards any additional keys in
platform_data that the table above lists for the post type you publish, and no others. Any other key, including a key listed for another post type, is not sent, and the response lists each one as a validation warning naming the key. For example, link on a single photo returns a warning and the photo publishes without it. Facebook has no AI-generated label: is_ai_generated returns a warning and is not sent.
Photo post
Provide a single image entry inmedia. Photo posts also accept alt_text, min_age, max_age, countries, place, and no_story; see the table above.
Multi-photo album
Provide 2 to 10 image entries inmedia to publish a multi-photo album. The entries are published as a single album post with one caption.
link, cta_type plus cta_link, age and country targeting, and place in the target’s platform_data:
- Minimum 2, maximum 10 photos per album.
- Images only. Including a video entry (any of
.mp4,.mov,.avi,.mkv,.webm) in a 2+ itemmedialist returns a validation error before any upload to Facebook.
Link carousel
Publish 2 to 10 link cards in one post by settingchild_attachments instead of media or link. This is different from a multi-photo album: no media is uploaded, and each card carries its own link, title, and description.
child_attachments on a post with media returns a validation error. link set together with child_attachments is not sent and returns a validation warning.
Video post
Provide a single video entry inmedia. It is published as a Page video. Video posts also accept min_age, max_age, countries, place, no_story, content_category, content_tags, embeddable, secret, and social_actions; see the table above.
Reel
Publish a short-form vertical video as a Page Reel by settingcontent_type: "reel" in the target’s platform_data. Provide exactly one vertical video entry in media. Facebook processes Reels before they go live. SocialAPI waits up to about 10 minutes for that to finish. After that, the target fails with 504 platform.facebook.reel_timeout. If Facebook cannot process the video, the target fails with 422 platform.facebook.reel_processing_failed.
share_to_feed defaults to true, which shares the Reel to the Page feed on Facebook as well as the Reels tab. List posts does not return a Reel with either value. Reels also accept title and place; see the table above for every option.
Requirements: exactly one video, vertical orientation (9:16), and a duration of 3 to 90 seconds. SocialAPI warns when the duration is outside that range; Facebook enforces the aspect ratio at publish time and rejects videos that do not comply.
Story
Publish a 24-hour Page Story by settingcontent_type: "stories" in the target’s platform_data. Provide exactly one photo or video entry in media. A video Story waits up to about 10 minutes for Facebook to process it. After that, the target fails with 504 platform.facebook.story_timeout. If Facebook cannot process the video, the target fails with 422 platform.facebook.story_processing_failed.
Stories carry no caption, link, call-to-action, or audience targeting. text is ignored, and any platform_data key other than content_type is not sent and returns a validation warning.
content_type to "stories", plural, to publish a Story. The singular "story" is not recognized and publishes a standard feed post instead, with a validation warning. No other platform_data key applies to Stories.
Requirements and limits:
- Exactly one media item. Passing zero or more than one entry returns a validation error before any upload to Facebook.
- Photos: JPEG, BMP, PNG, GIF, or TIFF, up to 10 MB (keep PNGs under 1 MB).
- Videos: 9:16 vertical, 1080 by 1920 recommended (minimum 540 by 960), 3 to 90 seconds, 24 to 60 fps.
- The photo or video must not have been used in a previously published post. Facebook rejects a Story whose media already appeared elsewhere, so upload a fresh asset for each Story.
- Stories are a Pages-only format and expire after 24 hours (see Stories expire).
First comment
Setfirst_comment to a string to post an automated comment immediately after publish. This is best-effort: if the comment fails (for example due to a temporary rate limit), the post is still considered published.
Page Stories are the one exception: a Story has no comments edge on the Graph API, so first_comment is skipped for content_type: "stories" targets. Every other post type (text, link, single photo, multi-photo album, single video, Reel) accepts one.
Scheduling
Setscheduled_at to an ISO 8601 timestamp (UTC) to defer publishing:
4. Update post
A published Facebook post cannot be edited through SocialAPI.PATCH /v1/posts/{pid} returns 409 post.state_invalid for any post whose status is not draft, scheduled, or failed, with the message “Only draft, scheduled, or failed posts can be edited”.
A post in draft, scheduled, or failed status can be edited with PATCH /v1/posts/{pid} before it publishes.
To correct a published post, delete it with DELETE /v1/posts/{pid} and publish a new post.
5. Delete post
account_id. DELETE /v1/posts/{pid} always removes every target.
6. Retrieve posts
UseGET /v1/posts to list posts. Filter by platform or account:
targets array with per-platform status and engagement metrics:
likesandcommentsare synced from Facebook.sharesis populated for Facebook posts.savesis not available on Facebook and is always0.metrics_synced_atreflects when SocialAPI last refreshed the metrics from Facebook.- A Reel reports
likes,comments, and a view count undermetrics.views(also undermetrics.extra.views). Itssharesstays0, because Facebook does not report a Reel’s share count to SocialAPI. - A target whose metrics cannot be read is returned with a structured
errorobject rather than omitted from the response. An absent target therefore means the post was never published to that platform, not that the refresh failed. Checkerror.codeto tell the cases apart:resource.not_foundmeans the platform did not return the post in its recent listing, andresource.not_supportedmeans the platform does not expose metrics for it.
Settings on published posts
A Facebook target can include asettings object with the options Facebook reports back for the published post:
settings is absent when Facebook reported none of these for the post. It is also returned for posts published outside SocialAPI, since it reflects what Facebook reports at the time of the read rather than what was sent through this API.
Media on published posts
A Facebook target includesplatform_media: every photo and video on the published post, album photos in order. It is returned for posts published outside SocialAPI too, so you can read the photos and videos of a Page’s existing posts.
Link and share posts have no
platform_media: their image is a preview of the linked site, not media the Page posted. A Reel has none either, since List posts does not return Reels, whatever share_to_feed is.
The links expire. Download the files when you read the post rather than storing the links. To get fresh links, call POST /v1/accounts/{id}/sync, then read the post again.
url is absent when Facebook does not expose a video’s file. The cover image is still included.
POST /v1/accounts/{id}/sync covers up to the 500 most recent posts on each Page of the account. Each account can be synced once every 5 minutes; an earlier call returns 429 accounts.sync_rate_limited with a Retry-After header. The account needs the posts.read permission: without it the call returns 403 account.permission_missing.
platform_media is separate from media, which lists what you sent when publishing through SocialAPI and is empty for posts published elsewhere.
7. Quirks, errors, and recovery
Page access
A Page access token does not expire on its own. A call returns401 platform.facebook.auth when the person revoked access or lost their role on the Page: reconnect the account. Connection rules, including which Pages a connection holds, are in Facebook connect.
Multi-photo album semantics
A multi-photo album publishes as one post or not at all. Mixing images and videos, more than 10 images, or a Reel with more or fewer than one video fails pre-publish validation with400 publishing.validation_failed. With skip_validation: true, the target fails with validation.media_mixed, validation.media_too_many, or validation.media_invalid.
First comment is non-blocking
Iffirst_comment is set and the comment fails after publish, the post stays published. Nothing in the post response reports the failed comment.
Stories expire
Facebook Page Stories are visible for 24 hours. The post stays in SocialAPI, soGET /v1/posts can return a Story that is no longer live. A photo or video that appeared in an earlier post is refused as a Story: upload a fresh file for each Story.
Posting caps
SocialAPI refuses a publish that would pass 25 posts in an hour or 100 posts in 24 hours for one Page, with429 publishing.velocity_limit. A scheduled post is held and published when the window clears. When Facebook refuses first, the target fails with 429 platform.facebook.rate_limit. See Posting velocity caps.
Errors on a failed target
A publish that fails after the request returned puts a structured error on the target, intargets[].error:
401 platform.facebook.auth: the access token is invalid or revoked. Reconnect the account.429 platform.facebook.rate_limit: Facebook’s own limit. Wait, then retry.platform.facebook.<code>: Facebook refused the request with its own error code and message. The HTTP status is502unless the code has its own mapping, such as404 platform.facebook.100or403 platform.facebook.230. Readmessage. Common causes are a missing Page scope, a post that no longer exists, and an invalid media URL.502 platform.facebook.api_error: a failure reaching Facebook, or a response with no usable error.422 platform.facebook.reel_processing_failedand422 platform.facebook.story_processing_failed: Facebook could not process the video.504 platform.facebook.reel_timeoutand504 platform.facebook.story_timeout: Facebook did not finish processing the video in about 10 minutes.
Recovery
- Rate limit. Wait, then send
POST /v1/posts/{pid}/retry. See Delivery. - Auth error. Reconnect the Facebook account through the OAuth flow to get a fresh token.
- API error. Read
message, fix the cause, and retry.
8. Full worked example
The following example publishes a link preview post, then checks the metrics after publish. Step 1: Publish the post9. Required OAuth scopes
SocialAPI’s Meta app requests these scopes during the OAuth flow. You configure nothing. The full list, includingbusiness_management, is in Facebook scopes. Publishing uses these:
The scopes a scoped API key needs, the credit cost of a post, and the MCP tools that publish are on Publishing.