Reelspan publishes to Instagram professional accounts through Meta's Graph API. You send the video or photos once; Reelspan creates the Instagram media, waits for Instagram to process it, publishes it and returns the permalink.
What you can post
| Post | How | Notes |
|---|---|---|
| Reel | POST /v1/posts/video |
The default for a video |
| Video Story | POST /v1/posts/video with media_type=STORIES |
No caption |
| Photo post | POST /v1/posts/photos with one photo |
|
| Carousel | POST /v1/posts/photos with 2 to 10 items |
Photos and videos can be mixed |
| Photo Story | POST /v1/posts/photos with media_type=STORIES |
No caption |
Instagram has no text-only posts and no documents. Reelspan handles for you:
- JPEG only. Instagram takes JPEG photos. PNG, WebP, HEIC and JPEGs over 8 MB are converted to a JPEG under 8 MB first; the result says so in
warnings. - Mixed carousels. Videos sent in
photos[]become video items of the carousel. Each video item is processed before the carousel is made. - Processing. Instagram fetches the media from a short-lived signed link and processes it. Reelspan waits for it (up to 15 minutes), publishes it, then reads back the post's permalink.
Connect the account
Instagram connects through Facebook Login, so the account needs to be set up the way Meta's API requires:
- The Instagram account is a professional account (Business or Creator). Switch in the Instagram app under Settings → Account type and tools.
- It is linked to a Facebook Page you manage.
- In Reelspan, go to Accounts → Instagram, sign in with the Facebook account that manages that Page, and share the Page when Facebook asks.
Reelspan connects the Instagram account linked to the first shared Page that has one. If you manage several, share only the Page whose Instagram account you want on this profile. The same Facebook sign-in can connect Facebook Pages too; each is its own connection.
Example
A Reel with a co-author and a custom cover:
curl -X POST https://api.reelspan.com/v1/posts/video \
-H "Authorization: Bearer $REELSPAN_API_KEY" \
-F "user=my-brand" \
-F "platform[]=instagram" \
-F "instagram_title=Behind the scenes of our spring shoot 🌸" \
-F "collaborators=@partnerstudio" \
-F "share_to_feed=true" \
-F "cover_url=https://example.com/cover.jpg" \
-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: ['instagram'],
video: { data: await readFile('launch.mp4'), name: 'launch.mp4', type: 'video/mp4' },
extra: {
instagram_title: 'Behind the scenes of our spring shoot 🌸',
collaborators: '@partnerstudio',
share_to_feed: true,
cover_url: 'https://example.com/cover.jpg',
},
});from reelspan import Reelspan
reelspan = Reelspan()
post = reelspan.posts.video(
"my-brand", ["instagram"], "launch.mp4",
extra={
"instagram_title": "Behind the scenes of our spring shoot 🌸",
"collaborators": "@partnerstudio",
"share_to_feed": True,
"cover_url": "https://example.com/cover.jpg",
},
)A carousel is the same request on POST /v1/posts/photos with several photos[], and alt_text[] (or instagram_alt_text[]) in the same order.
Fields
| Field | Type | Values | What it does |
|---|---|---|---|
instagram_title |
string | up to 2,200 characters | The caption. Falls back to title. Longer text is cut. Not used on Stories. |
media_type |
string | Video: REELS (default), STORIES. Photos: FEED (default), STORIES |
Post a Story instead of a Reel or feed post. |
share_to_feed |
boolean | default true |
Reels: also show the Reel in the profile's feed. false keeps it on the Reels tab. |
collaborators |
string | comma-separated usernames, up to 3 | Reels: accounts invited to co-author the Reel. A leading @ is removed. |
cover_url |
string | public https URL of an image | Reels: the cover image. You can also upload the image as a cover file or send cover_media_id. |
thumb_offset |
number | milliseconds | Reels: the frame used as the cover when there is no cover image. |
audio_name |
string | Reels: the name shown for the Reel's audio. | |
location_id |
string | numeric Facebook place id | Reels: tags a location. A non-numeric value is ignored with a warning. |
share_mode |
string | CUSTOM (a normal Reel), TRIAL_REELS_SHARE_TO_FOLLOWERS_IF_LIKED, or another trial mode |
Reels: post a trial Reel, shown to non-followers first. With TRIAL_REELS_SHARE_TO_FOLLOWERS_IF_LIKED Instagram shares it with followers if it performs well; any other value except CUSTOM makes a trial Reel you share with followers yourself. |
instagram_alt_text |
string or list | up to 1,000 characters each | Photo alt text: one text for every photo, or one per photo in order. Falls back to alt_text. Not used on Stories or video items. |
instagram_first_comment |
string | up to 2,200 characters | A comment posted under the new post. Falls back to first_comment. |
Limits
- Caption: 2,200 characters. Instagram also allows at most 30 hashtags and 20 mentions.
- Carousel: up to 10 items; with more, the first 10 are used and the result says so.
- Photos: JPEG up to 8 MB (other photos are converted). Instagram takes feed photos from 4:5 to 1.91:1.
- Video size: your plan's upload limit (see Plans and limits).
- Shapes: 9:16 for Reels and Stories, 4:5 or 1:1 for feed posts.
Good to know
- Stories carry no caption, and a photo Story uses the first photo only.
- Collaborators, covers, location, audio name and trial Reels apply to Reels; they are ignored on Stories and photo posts.
- Result extras:
container_id(Instagram's media container) and, for videos,media_type. - First comment: Reelspan posts it under the new post. If Meta refuses it (for example a missing comment permission on the connection), the post stays up and the result carries
first_comment: "failed"and a warning. - Analytics: account followers, following and post count; per post, likes and comments.
Errors
error_code |
What happened | What to do |
|---|---|---|
instagram_processing_failed |
Instagram couldn't process the media (wrong format, length or shape) | Check the file against Instagram's rules and post again. |
instagram_processing_timeout |
Instagram took more than 15 minutes | Reelspan retries it; check Instagram before posting again. |
meta_permission_denied |
The connection lacks a permission Meta needs | Reconnect Instagram 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 token expired or was revoked | Reconnect Instagram. |
media_required |
The request had no video or photo for Instagram | Send media: Instagram has no text posts. |