1. Overview
Facebook publishing uses the Meta Graph API directly against your connected Facebook Page. SocialAPI selects the correct Graph API endpoint based on the content type: text and link posts go to/{page-id}/feed, single-photo posts to /{page-id}/photos, single-video posts to /{page-id}/videos, and multi-photo albums use a two-step upload-then-feed flow. Two richer formats are opted into explicitly with platform_data.content_type: Reels (content_type: "reel") publish through the Reels API, and 24-hour Stories (content_type: "stories") publish through the photo or video Stories API. Every format is described below.
2. Supported media
Route selection is mostly automatic, driven by how many
media_ids you pass:
media_idsis empty → text or link post on/{page-id}/feedmedia_idshas one entry → photo or video endpoint based on the file extensionmedia_idshas 2 to 10 entries → 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.
Caption limit: Follows Facebook’s standard post message limit (approximately 63,206 characters, though shorter posts perform better).
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 or use a single Reel with image overlays.
- Each photo is uploaded as an unpublished photo, which Facebook retains for approximately 24 hours. The follow-up feed call happens immediately, so this expiry only matters if the feed call fails. In that case the uploaded photos are abandoned and you can safely retry the 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.
Platform data fields
Pass these inside the target’splatform_data object (keys are read directly, not nested under a facebook key). These fields apply to text, link posts, and multi-photo albums. Single-photo posts honor alt_text; single-video posts honor title. Other platform_data keys are silently ignored for those post types.
Only the documented fields above are forwarded to the Graph API; any additional keys in
platform_data are silently ignored.
Photo post
Provide a single image entry inmedia_ids. The alt_text platform_data field is forwarded as alt_text_custom on the photo; all other platform_data keys are ignored for single-photo posts.
Multi-photo album
Provide 2 to 10 image entries inmedia_ids to publish a multi-photo album. SocialAPI handles the two-step Graph API flow internally: each photo is uploaded with published=false to obtain a media_fbid, then a single /{page-id}/feed call attaches all photo IDs via attached_media[] and sets the caption.
platform_data IS honored for albums. The link, cta_type plus cta_link, and age targeting fields are forwarded to the feed call:
- Minimum 2, maximum 10 photos per album.
- Images only. Including a video entry (any of
.mp4,.mov,.avi,.mkv,.webm) in a 2+ itemmedia_idsreturns a validation error before any upload to Facebook.
Video post
Provide a single video entry inmedia_ids. SocialAPI detects the video extension and routes to /{page-id}/videos. The title platform_data field is forwarded as the video title; all other platform_data keys are ignored for single-video posts.
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_ids. SocialAPI runs Facebook’s Reels publishing flow (upload, processing, publish). The request blocks until the Reel is ready or published, polling for up to about 10 minutes (120 status checks at 5-second intervals). If the Reel does not finish processing within that window, the publish fails with 504 Gateway Timeout.
The platform_data object lives on the target (inside the targets array), and its keys are read directly (do not nest them under a facebook key).
platform_data):
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_ids, and SocialAPI picks the right flow from the media type: a photo is uploaded as an unpublished photo and then published to /{page-id}/photo_stories, while a video runs Facebook’s three-phase /{page-id}/video_stories flow (upload, processing, publish). For a video, the request blocks until processing finishes, polling for up to about 10 minutes (120 status checks at 5-second intervals); if it does not finish in that window, the publish fails with 504 Gateway Timeout.
Stories carry no caption, link, call-to-action, or audience targeting, so any text or platform_data field other than content_type is ignored.
platform_data):
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.
Scheduling
Setscheduled_at to an ISO 8601 timestamp (UTC) to defer publishing:
4. Update post
Facebook supports editing the message text of a post that was created by the same app. Media cannot be changed after publish. UsePATCH /v1/posts/:pid with a text field:
POST /{page-id}_{post-id} with the new message value. Only the text field is forwarded; all other patch fields are ignored for Facebook targets.
Limitation: Only posts created by your app can be updated. Posts imported from the platform (via sync) may return a 400 from Facebook if the app does not own them.
5. Delete post
DELETE /{page-id}_{post-id} on the Graph API. If the post no longer exists on Facebook, the call returns success.
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 periodically from the Graph API.sharesis populated for Facebook posts. Facebook is the only platform where SocialAPI reports a non-zero share count.savesis not exposed by the Facebook Pages API and is always0.metrics_synced_atreflects when SocialAPI last refreshed the metrics from Facebook.
7. Quirks, errors, and recovery
Page token lifetime
Facebook Page tokens derived from long-lived user tokens do not expire. Once an account is connected, the token remains valid indefinitely unless the user revokes app access or changes their password. Reconnection is only needed if you see anauth error.
Multi-page OAuth
When a user completes the Facebook OAuth flow, SocialAPI connects all Facebook Pages that the user manages in a single OAuth exchange. Each page becomes a separate connected account entry. Users do not need to repeat the OAuth flow for additional pages.platform_data forwarding rules
The target’splatform_data block is forwarded to the Graph API for text/link posts and for multi-photo albums (both go through the /{page-id}/feed endpoint). For single-photo and single-video posts, most platform_data keys are ignored: alt_text is honored for single-photo posts and title is honored for single-video posts. For Reels, content_type and share_to_feed apply; for Stories, only content_type applies (Stories take no caption, link, or targeting). All other keys are silently dropped for those post types.
Multi-photo album semantics
Multi-photo albums (2 to 10 image entries inmedia_ids) use a two-step flow: each photo is uploaded with published=false, then attached to a single feed post. The unpublished photos Facebook stores during step one expire after about 24 hours, so if the second step fails the photos are simply abandoned and you can retry the entire post. Mixing images and videos in the same album returns a validation error before any upload happens, and passing more than 10 entries also fails validation.
First comment is non-blocking
Iffirst_comment is set and the comment fails after publish, the post remains published. The comment failure is logged but does not roll back or change the post status.
Stories expire
Facebook Page Stories are visible for 24 hours and then disappear from the Page. The post record in SocialAPI is not removed when the story expires on Facebook, so aGET /v1/posts result may still reference a story that is no longer live. Stories are also single-use per asset: the photo or video must not have appeared in a previously published post, or Facebook rejects the publish. Upload a fresh media item for each Story.
Reviews deprecated
The Facebook Graph API v22.0 removed the reviews edge.GET /v1/inbox/reviews for a Facebook account returns 501 Not Implemented. This is a platform-level deprecation and cannot be worked around.
DM 24-hour window
Facebook Messenger only allows pages to send outbound DMs within a 24-hour window after the user last messaged the page. Attempting to send outside this window returns a platform error. SocialAPI surfaces this as anapi_error.
Error shapes
When a publish fails, the post target’serror field contains a structured error:
Recovery
- Rate limit: Retry the post via
POST /v1/posts/:pid/retryafter waiting. SocialAPI applies exponential backoff for scheduled retries. - Auth error: Disconnect and reconnect the Facebook account through the OAuth flow to obtain a fresh token.
- API error: Check the
messagefield for the Graph API error description. Common causes include missing page permissions, a post that no longer exists, or an invalid media URL.
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 managed Meta App requests the following scopes on your behalf during the OAuth flow. This is informational, you do not need to configure anything.
To verify which scopes your connected account has granted, call
GET /v1/accounts/:id/limits.