RelayAPI

Facebook API

Schedule and automate Facebook Page posts with RelayAPI — feed posts, multi-image, stories, reels, and first comments.

Quick Reference

PropertyValue
Platform keyfacebook
Auth methodOAuth 2.0
Character limit63,206 (truncated at ~480 with "See more")
Images per post10
Videos per post1
Image formatsJPEG, PNG, GIF (WebP auto-converted to JPEG)
Image max size10 MB
Video formatsMP4, MOV, AVI
Video max size1 GB
Video max duration240 min (feed), 120 sec (stories)
Post typesFeed (text/image/video/multi-image), Story, Reel
SchedulingYes
AnalyticsYes (impressions, likes, comments, shares, clicks, views)

Client optionsTypeScript · Python REST/OpenAPI · Go · Java · REST API

Before You Start

Facebook API posting only works with Pages — you cannot post to personal profiles. The user must be a Page Admin or Editor. After connecting via OAuth, you must select which Facebook Page to post to. Facebook tokens expire frequently, so subscribe to the account.disconnected webhook to catch token expirations proactively. Images over 4 MB are frequently rejected in practice even though the stated limit is higher.

Published Page post editing requires pages_manage_posts; comment editing and engagement require pages_manage_engagement; Messenger read receipts require pages_messaging. Reauthorize an older Facebook Page connection that lacks a needed grant; a refresh token does not grant new permissions.

Quick Start

Post to a Facebook Page:

import Relay from '@relayapi/sdk';

const client = new Relay();

const post = await client.posts.create({
  content: 'Exciting news from our Page!',
  targets: ['facebook'],
  scheduled_at: 'now'
});

console.log(post.id); // post_abc123

Content Types

Text-Only Post

Facebook is one of few platforms that supports text-only posts. First ~480 characters are visible before the "See more" fold.

const post = await client.posts.create({
  content: 'Just a text update for our followers.',
  targets: ['facebook'],
  scheduled_at: 'now'
});

Single Image Post

const post = await client.posts.create({
  content: 'Check out this photo!',
  targets: ['facebook'],
  media: [
    { url: 'https://cdn.example.com/photo.jpg', type: 'image' }
  ],
  scheduled_at: 'now'
});

Multi-Image Post (Up to 10)

Up to 10 images per post. Cannot mix images and videos in the same post.

const post = await client.posts.create({
  content: 'Photo dump from our event!',
  targets: ['facebook'],
  media: [
    { url: 'https://cdn.example.com/photo1.jpg', type: 'image' },
    { url: 'https://cdn.example.com/photo2.jpg', type: 'image' },
    { url: 'https://cdn.example.com/photo3.jpg', type: 'image' }
  ],
  scheduled_at: 'now'
});

Video Post

Single video per post. Up to 4 GB, max 240 minutes for feed videos.

const post = await client.posts.create({
  content: 'Watch our latest video!',
  targets: ['facebook'],
  media: [
    { url: 'https://cdn.example.com/video.mp4', type: 'video' }
  ],
  scheduled_at: 'now'
});

Story

Media is required for stories. Text captions are not displayed on Facebook Stories. Interactive stickers are not available via the API.

const post = await client.posts.create({
  targets: ['facebook'],
  media: [
    { url: 'https://cdn.example.com/story.jpg', type: 'image' }
  ],
  scheduled_at: 'now',
  target_options: {
    facebook: {
      content_type: 'story'
    }
  }
});

Reel

Single vertical video, 3-60 seconds. Reels support a separate title field.

const post = await client.posts.create({
  content: 'Behind the scenes of our latest shoot',
  targets: ['facebook'],
  media: [
    { url: 'https://cdn.example.com/reel.mp4', type: 'video' }
  ],
  scheduled_at: 'now',
  target_options: {
    facebook: {
      content_type: 'reel',
      title: 'Studio day'
    }
  }
});

Post with First Comment

Automatically post a first comment after publishing. Useful for adding links without suppressing reach.

const post = await client.posts.create({
  content: 'New product launch!',
  targets: ['facebook'],
  media: [
    { url: 'https://cdn.example.com/product.jpg', type: 'image' }
  ],
  scheduled_at: 'now',
  target_options: {
    facebook: {
      first_comment: 'Link to purchase: https://shop.example.com'
    }
  }
});

First comments only work with feed posts. They are not supported on Stories or Reels.

Multi-Page Posting

Post to multiple Facebook Pages in a single request by targeting different account IDs.

const post = await client.posts.create({
  content: 'News from all our brands!',
  targets: ['acc_fb_brand1', 'acc_fb_brand2'],
  scheduled_at: 'now'
});

Media Requirements

Images

PropertyFeed PostStory
Max images101
FormatsJPEG, PNG, GIF (WebP auto-converted)JPEG, PNG
Max file size4 MB4 MB
Recommended1200 x 630 px1080 x 1920 px

Videos

PropertyFeed VideoStoryReel
Max videos111
FormatsMP4, MOVMP4, MOVMP4, MOV
Max file size4 GB4 GB
Max duration240 min120 sec60 sec
Min duration1 sec1 sec3 sec
Recommended1280 x 720 min, H.264, 30fps1080 x 19209:16 vertical

target_options Fields

All fields go inside target_options.facebook on your post request.

FieldTypeDescription
contentstringOverride content for Facebook specifically
mediaobject[]Override media for Facebook specifically
content_typestring"story" or "reel" (default: feed post)
titlestringReel title (only for reels, separate from content/caption)
first_commentstringAuto-posted first comment (feed posts only, not stories or reels)
publishedbooleanFeed only; false creates an unpublished provider-side Page post and cannot be combined with first_comment
place_idstringNumeric Page/location ID for feed posts or Reels; unavailable for Stories
targetingobjectFeed-only strict audience restriction; people outside it cannot view the post
feed_targetingobjectFeed-only preferred News Feed audience; people outside it may still see the post
reel_statestringReel only: DRAFT, SCHEDULED, or PUBLISHED
reel_scheduled_publish_timedatetimeRequired only for reel_state: 'SCHEDULED'; more than 10 minutes and no more than 29 days ahead
page_idstringLegacy exact-match assertion for the Page selected during connection; it cannot retarget the credential
await client.posts.create({
  content: 'A local preview before launch',
  targets: ['facebook'],
  scheduled_at: 'now',
  target_options: {
    facebook: {
      published: false,
      place_id: '123456789012345',
      targeting: {
        geo_locations: { countries: ['GB'] },
        age_min: 18,
      },
      feed_targeting: {
        geo_locations: { cities: [{ key: '2420605', radius: 20, distance_unit: 'mile' }] },
      },
    },
  },
});

Facebook colored/background posts are not exposed: RelayAPI has no verified official Page-create contract for that field and rejects rather than guessing.

Common Errors

ErrorCauseFix
Photos should be smaller than 4 MBImage exceeds practical size limitReduce to under 4 MB. Use JPEG or PNG.
Missing or invalid image fileCorrupt file, wrong format, or inaccessible URLVerify the URL returns actual media bytes. Use JPEG or PNG under 4 MB.
Unable to fetch video from URLVideo URL is inaccessible to Facebook serversUse a direct, publicly accessible CDN URL.
Tokens expiredOAuth token has expiredReconnect the account. Facebook tokens have shorter lifespans than most platforms.
Confirm your identityFacebook security check triggeredThe user must complete identity verification directly on Facebook.

Known Quirks

  • Pages only — you cannot post to personal Facebook profiles via the API.
  • Cannot mix images and videos in the same post.
  • WebP images are auto-converted to JPEG by Facebook.
  • Story text captions are not displayed — only the media is shown.
  • Story interactive stickers are not available via the API.
  • Facebook often rejects images over 4 MB in practice, even though the documented limit is higher.
  • Tokens expire frequently — subscribe to the account.disconnected webhook to detect token expirations.
  • GIFs should use type: "video" — they auto-play and loop when sent as video type.
  • First ~480 characters visible before the "See more" fold on feed posts.

Published edits and social actions

RelayAPI can edit published Page post text and owned comments, hide/unhide comments, like/unlike posts, and send Messenger read receipts for persisted inbound messages. These provider writes require durable idempotency and the appropriate pages_manage_posts, pages_manage_engagement, or pages_messaging grant. See Published Edits and Social Actions.

Automations

Facebook Messenger is a Tier 1 automation platform — full inbound conversational event coverage and 9 outbound send node types.

Triggers

TypeFires on
facebook_dmInbound Messenger DM
facebook_commentNew comment on a Page post
facebook_mentionPage @-mentioned
facebook_postbackGet Started / persistent menu button
facebook_reactionMessage reaction added/removed
facebook_optinSend-to-Messenger widget / Ref URL opt-in
facebook_feed_postNew post on the Page feed

Send nodes

All messaging nodes hit POST {GRAPH_BASE.facebook}/{page-id}/messages. Comment operations use the Graph API comment endpoints.

NodeRequired fields
facebook_send_texttext
facebook_send_mediaurl, media_type ∈ image|video|audio|file
facebook_send_templatepayload (raw Messenger template object)
facebook_send_quick_repliestext, quick_replies[] (≤13)
facebook_send_button_templatetext, buttons[] (≤3)
facebook_reply_to_commentmessage (+ optional comment_id)
facebook_private_replytext (+ optional comment_id)
facebook_hide_commentcomment_id (or falls back to trigger payload)
facebook_sender_actionaction ∈ typing_on|typing_off|mark_seen

The HUMAN_AGENT message tag is for human-handled surfaces only, not an automation escape hatch. Automated DMs must land inside the 24-hour customer-service window.

Found something wrong? Help us improve this page.

On this page