Reelspan publishes to Facebook Pages with Meta's Graph API. You send the post once; Reelspan uploads it to the Page you chose, waits until Facebook reports a Reel as published, and returns its link. Posting to personal profiles and groups isn't possible through Meta's API.
What you can post
| Post | How | Notes |
|---|---|---|
| Reel | POST /v1/posts/video |
The default for a video |
| Page video | POST /v1/posts/video with facebook_media_type=VIDEO |
A regular Page video, any shape, with a title |
| Video Story | POST /v1/posts/video with facebook_media_type=STORIES |
No caption |
| Photo post | POST /v1/posts/photos |
One photo, or up to 30 in one post |
| Photo Stories | POST /v1/posts/photos with facebook_media_type=STORIES |
Each photo becomes its own Story, up to 10 |
| Text post | POST /v1/posts/text |
With an optional link preview |
Reelspan handles for you:
- Pulling, not streaming. Facebook fetches the video itself from a signed link, which is faster for large files.
- Multi-photo posts. Each photo is uploaded first, then attached to one Page post in order.
- Waiting for the Reel. Reelspan follows the Reel until Facebook reports it published (up to 10 minutes), so the link works when you get it.
Connect the account
Facebook connects through Facebook Login: in the dashboard go to Accounts → Facebook, or send a white-label connect link. Sign in with a Facebook account that manages the Page, and select the Pages to share when Facebook asks.
- One Page shared: every post goes there.
- Several Pages shared: choose the default under Accounts → Facebook → Details or with
POST /v1/facebook/page, or name the Page on each post withfacebook_page_id. Without either, the post fails withfacebook_page_required.
To add a Page later, reconnect Facebook and select it.
Example
A Reel to a chosen Page:
curl -X POST https://api.reelspan.com/v1/posts/video \
-H "Authorization: Bearer $REELSPAN_API_KEY" \
-F "user=my-brand" \
-F "platform[]=facebook" \
-F "facebook_page_id=104512345678901" \
-F "facebook_title=Spring collection is live" \
-F "[email protected]"import { Reelspan } from 'reelspan';
import { readFile } from 'node:fs/promises';
const reelspan = new Reelspan();
const post = await reelspan.posts.video({
user: 'my-brand',
platforms: ['facebook'],
video: { data: await readFile('launch.mp4'), name: 'launch.mp4', type: 'video/mp4' },
extra: { facebook_page_id: '104512345678901', facebook_title: 'Spring collection is live' },
});from reelspan import Reelspan
reelspan = Reelspan()
post = reelspan.posts.video(
"my-brand", ["facebook"], "launch.mp4",
extra={"facebook_page_id": "104512345678901", "facebook_title": "Spring collection is live"},
)A text post with a link preview:
curl -X POST https://api.reelspan.com/v1/posts/text \
-H "Authorization: Bearer $REELSPAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"user": "my-brand", "platform": ["facebook"], "title": "Our spring lookbook is out.", "facebook_link": "https://example.com/lookbook"}'await reelspan.posts.text({
user: 'my-brand',
platforms: ['facebook'],
title: 'Our spring lookbook is out.',
extra: { facebook_link: 'https://example.com/lookbook' },
});reelspan.posts.text("my-brand", ["facebook"], "Our spring lookbook is out.", extra={"facebook_link": "https://example.com/lookbook"})Choose the Page
GET /v1/facebook/pages?profile=my-brand lists the Pages shared with this profile's Facebook connection, with each Page's followers and likes. selected marks the Page chosen as the default, also named in selected_page_id and selected_page_name.
curl "https://api.reelspan.com/v1/facebook/pages?profile=my-brand" \
-H "Authorization: Bearer $REELSPAN_API_KEY"const { pages } = await reelspan.request('GET', '/v1/facebook/pages', { query: { profile: 'my-brand' } });pages = reelspan.request("GET", "/v1/facebook/pages", query={"profile": "my-brand"})["pages"]{
"success": true,
"pages": [
{ "id": "104512345678901", "name": "My Brand", "picture": "https://…", "account_id": "104512345678901", "selected": true, "followers": 18240, "likes": 17955 },
{ "id": "209876543210987", "name": "My Brand Outlet", "picture": null, "account_id": "104512345678901", "selected": false, "followers": 950, "likes": null }
],
"selected_page_id": "104512345678901",
"selected_page_name": "My Brand"
}The list comes from the connection, so it shows the Pages shared when it was made. followers and likes are read live from Facebook and are null when it doesn't say. A profile with no Facebook account gets 404 profile_platform_mapping_invalid.
To make a Page the default, send its id to POST /v1/facebook/page (needs the profiles scope). A post that names no facebook_page_id then goes there.
curl -X POST https://api.reelspan.com/v1/facebook/page \
-H "Authorization: Bearer $REELSPAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"profile": "my-brand", "facebook_page_id": "209876543210987"}'await reelspan.request('POST', '/v1/facebook/page', { json: { profile: 'my-brand', facebook_page_id: '209876543210987' } });reelspan.request("POST", "/v1/facebook/page", json_body={"profile": "my-brand", "facebook_page_id": "209876543210987"}){ "success": true, "facebook_page_id": "209876543210987", "facebook_page_name": "My Brand Outlet" }A Page that wasn't shared with Reelspan gets 404 facebook_page_not_connected: reconnect Facebook and select it. DELETE /v1/facebook/page with {"profile": "my-brand"} clears the choice; then each post needs facebook_page_id, unless only one Page is connected.
Page details
GET /v1/facebook/page-info?profile=my-brand reads a Page's details from Facebook: name, username, about, description, website, phone, emails, opening hours, link, category, picture, cover, followers and likes. Send page_id for another of the connected Pages; without it, the chosen Page (or the only one) is used, and with several Pages and none chosen the answer is 400 facebook_page_required.
curl "https://api.reelspan.com/v1/facebook/page-info?profile=my-brand" \
-H "Authorization: Bearer $REELSPAN_API_KEY"{
"success": true,
"page_id": "104512345678901",
"page": {
"id": "104512345678901",
"name": "My Brand",
"username": "mybrand",
"about": "Everyday bags, made to last.",
"website": "https://example.com",
"phone": "+44 20 7946 0000",
"emails": ["[email protected]"],
"hours": { "mon_1_open": "09:00", "mon_1_close": "17:00" },
"hours_list": [{ "day": "mon", "open": "09:00", "close": "17:00" }],
"category": "Clothing store",
"picture_url": "https://…",
"cover_url": "https://…",
"followers": 18240,
"likes": 17955
}
}hours is Facebook's own shape; hours_list is the same as a list. Fields Facebook has no value for are null. The details are read only: Reelspan can't change them.
Fields
| Field | Type | Values | What it does |
|---|---|---|---|
facebook_page_id |
string | a Page id from the list above | The Page to post to. Without it, the account's chosen Page (or its only Page). |
facebook_title |
string | up to 63,206 characters | The post text. Falls back to title. On a Reel it is also the Reel's title (first 255 characters). |
facebook_description |
string | Post text that takes the place of facebook_title when both are sent. Falls back to description. |
|
facebook_media_type |
string | Video: REELS (default), VIDEO, STORIES. Photos: STORIES, otherwise a post |
VIDEO posts a regular Page video instead of a Reel; STORIES a Story. |
video_state |
string | PUBLISHED (default), DRAFT |
Reels: DRAFT uploads the Reel without publishing it. |
facebook_unpublished_content_type |
string | SCHEDULED, DRAFT, ADS_POST |
VIDEO only: uploads the video without showing it on the Page, as this kind. |
facebook_no_story |
boolean | default false |
VIDEO and photo posts: publish without a story in followers' feeds. |
facebook_place_id |
string | the Page id of a place | Photo, text and VIDEO posts: tags a place. |
facebook_link |
string | URL | Text posts: a link Facebook shows as a preview card. facebook_link_url and link_url work too. |
facebook_alt_text |
string or list | up to 1,000 characters each | Photo alt text: one for every photo, or one per photo in order. Falls back to alt_text. |
facebook_first_comment |
string | up to 8,000 characters | A comment posted under the new post. Falls back to first_comment. |
Facebook uses the description before the caption: if you send a general
descriptionfor other networks (YouTube, LinkedIn), Facebook posts that text instead oftitle. Sendfacebook_titleand leavedescriptionout, or sendfacebook_descriptionwith the text you want.
Limits
- Post text: 63,206 characters. Stories carry no text.
- Photos: up to 30 in a post (more are left out), up to 10 Story photos. Each photo up to 10 MB.
- Video size: your plan's upload limit (see Plans and limits).
- Shapes: 9:16 for Reels and Stories; 16:9 also works.
Good to know
- Reel or Page video. A video is a Reel unless you send
facebook_media_type=VIDEO. A Page video can be any shape and length;facebook_titleis its title (first 255 characters) and the post text is its description. Reelspan doesn't wait for Facebook to finish processing a Page video. - A slow Reel still counts. If Facebook is still processing after 10 minutes, Reelspan returns the Reel's link anyway; it starts working shortly after.
- Result extras:
page_id, and for Reelsvideo_idandvideo_state; for Page videosvideo_idandmedia_type: "VIDEO"; for multi-photo postsphoto_ids; for several Storiesstory_ids. - First comment: Reelspan posts it as the Page. If Meta refuses it (for example a missing permission on the connection), the post stays up and the result carries
first_comment: "failed"and a warning. - Analytics: Page followers and likes; per post, likes and comments.
After posting
- Delete a post, Reel or video with Unpublish.
- Edit a post's text with Edit a post. On a Reel or Page video,
text(ordescription) changes the description andtitlethe title. - Posts made outside Reelspan work too: name them with
platform,userand the Facebook post id.
Errors
error_code |
What happened | What to do |
|---|---|---|
facebook_page_required |
Several Pages are connected and none was chosen | Send facebook_page_id, or choose the Page in the dashboard. The error lists the Pages. |
facebook_page_not_connected |
facebook_page_id names a Page that wasn't shared |
Reconnect Facebook and select that Page. |
unsupported_media_type |
facebook_media_type isn't REELS, VIDEO or STORIES |
Use one of those. |
facebook_processing_failed |
Facebook couldn't process the Reel | Read error; check the file and post again. |
media_required |
A Story had no photo or video | Send media with Stories. |
meta_permission_denied |
The connection lacks a permission, or the Page role changed | Reconnect Facebook and accept every permission. |
meta_rate_limited |
Meta's rate limit was hit | Reelspan retries it later. |
meta_error |
Meta refused the request | Read error for Meta's message. |
reauth_required |
The login expired or was revoked | Reconnect Facebook. |