Skip to content
reelspanDocs

Publish

Post photos

Publish one photo or a carousel of up to 35 to Instagram, TikTok, Pinterest, X, LinkedIn and more at once, with alt text and per-network crops.

POSTapi.reelspan.com/v1/posts/photosTry it →

Send one photo or a carousel as multipart/form-data, in order, with the profile in user and each network in a repeated platform[] field. Each network gets the photos in the form it takes, and the answer has one result per network.

curl -X POST https://api.reelspan.com/v1/posts/photos \
  -H "Authorization: Bearer $REELSPAN_API_KEY" \
  -H "Idempotency-Key: spring-range-01" \
  -F "user=my-brand" \
  -F "platform[]=instagram" \
  -F "platform[]=x" \
  -F "platform[]=linkedin" \
  -F "title=The spring range is here" \
  -F "photos[][email protected]" \
  -F "photos[][email protected]" \
  -F "alt_text[]=A red mug on a wooden table" \
  -F "alt_text[]=The same mug in blue"

The answer is the same as for a video: one result per network under results, or a request_id when it runs on in the background. See Post status.

Where the photos come from

photos[] takes files, public https URLs, or both. You can also pass photo_media_ids[], files you uploaded earlier, to post the same photos again without sending them twice.

  • Up to 35 items in all. Extra files are dropped with a warning.
  • Each image can be up to 20 MB. Supported images: JPEG, PNG, WebP, GIF and HEIC.
  • When you mix sources, the carousel order is: uploaded files, then photo_media_ids[], then URLs, each in the order you sent them.
  • At least one photo is required; without one the answer is 400 MEDIA_REQUIRED.
  • One request can fetch at most 100 URLs, counting every network's own photo URLs too.
curl -X POST https://api.reelspan.com/v1/posts/photos \
  -H "Authorization: Bearer $REELSPAN_API_KEY" \
  -F "user=my-brand" \
  -F "platform[]=threads" \
  -F "title=From the shoot" \
  -F "photos[]=https://example.com/photo1.jpg" \
  -F "photos[]=https://example.com/photo2.jpg"

Which networks take photos

Instagram, Facebook, TikTok, X, Threads, LinkedIn, Pinterest, Bluesky, Reddit, Google Business, Telegram, Discord, Slack, Mastodon, Nostr, Lemmy, WordPress, Whop and Listmonk. YouTube, Dev.to and Hashnode don't: naming one gets 400 UNSUPPORTED_POST_TYPE.

How many photos each network shows, and the sizes and shapes it accepts, are on Photo requirements.

Instagram and Threads take videos and photos mixed in one carousel: put the video in photos[] (or its id in photo_media_ids[]) where it should appear. Every other network gets the photos only, and its result carries a warning that the videos were left out. A network left with no photos at all fails with media_required.

A different set per network

A network can get its own photos instead of photos[], for example a square crop for one network:

  • {network}_photos[]: public URLs, such as pinterest_photos[].
  • {network}_photo_media_ids[]: uploaded files, such as instagram_photo_media_ids[].
curl -X POST https://api.reelspan.com/v1/posts/photos \
  -H "Authorization: Bearer $REELSPAN_API_KEY" \
  -F "user=my-brand" \
  -F "platform[]=instagram" -F "platform[]=pinterest" \
  -F "title=New in" \
  -F "pinterest_board_id=1234567890" \
  -F "photos[][email protected]" \
  -F "pinterest_photos[]=https://example.com/photo1-2x3.jpg"

Alt text

alt_text[] gives one text per photo, in order. A single alt_text applies to every photo, and a JSON array in alt_text works too. {network}_alt_text overrides it for one network (for example x_alt_text). Alt text is sent to X, Instagram, Facebook, Threads, LinkedIn, Pinterest and Bluesky.

Captions

title is the caption on every network. {network}_title replaces it on one network (instagram_title, x_title, linkedin_title…), and {network}_description sets the longer text where a network has one. A long caption on X or Bluesky is posted as a thread.

Network settings

The fields below are the ones made for photo posts. Every network's full list is on its page under Networks.

Network Field What it does
Instagram media_type=STORIES Shares each photo as a Story instead of a feed post.
Facebook facebook_media_type=STORIES Shares each photo as its own Page Story.
TikTok privacy_level Who can see it, as for videos.
TikTok photo_cover_index Which photo (from 0) is the cover.
TikTok auto_add_music true lets TikTok add music.
TikTok tiktok_description The post's description, up to 4,000 characters. Its title is the first 90 characters of the caption.
Pinterest pinterest_board_id The board to pin to. Required.
Reddit reddit_subreddit The community to post in. Required.

Instagram takes photos from 4:5 to 1.91:1 and converts non-JPEG photos for you. A Pinterest carousel needs every photo in the same shape; use pinterest_photos[] to send it its own crops.

Later, queued or repeated

The same as for a video: scheduled_date with timezone, add_to_queue=true, or repeat_every with repeat_times. A scheduled answer is 202 with a job_id. See Scheduled posts, Queue and Scheduling and repeats.

Parameters

  • Idempotency-Keystring · header

    Makes retries safe: the same key within 24 hours returns the first answer (X-Idempotency-Key works too)

  • X-Request-Idstring · header

    Your own request_id (8-100 letters, digits, _ or -), and the idempotency key when none is sent

  • X-External-Idstring · header

    Same as the external_id field, for your own reference

Request body

multipart/form-data

  • userstringrequired

    Profile username

  • platform[]string[]required

    instagram, facebook, x, threads, bluesky, linkedin, pinterest, tiktok

  • photo_cover_indexstring

    TikTok: the photo (0-based) shown as the cover

  • auto_add_musicstring

    TikTok: let TikTok add music to the photo post

    truefalse

  • tiktok_descriptionstring

    TikTok: the photo post’s description (up to 4000); its title is the first 90 characters of the caption

  • photos[]string[]

    Photo files (binary) or public https URLs, in order; up to 35. Instagram and Threads also take videos here for a mixed carousel; the other networks get the photos only.

  • photo_media_ids[]string[]

    Photos (or, for a mixed carousel, videos) uploaded earlier with POST /v1/media/upload

  • <platform>_photos[]string[]

    Public URLs a platform gets instead of photos[], e.g. pinterest_photos[] cropped to one shape

  • <platform>_photo_media_ids[]string[]

    Uploaded photos a platform gets instead, e.g. instagram_photo_media_ids[]

  • titlestringrequired

    Caption

  • facebook_media_typestring

    Facebook: STORIES shares each photo as its own Page Story

    FEEDSTORIES

  • media_typestring

    Instagram: STORIES shares each photo as a Story

    FEEDSTORIES

  • alt_text[]string[]

    Alt text per photo, in order (or one alt_text for every photo, or a JSON array). {platform}_alt_text overrides it for one network. Sent to X, Instagram, Facebook, Threads, LinkedIn, Pinterest and Bluesky.

  • async_uploadstring

    truefalse

  • scheduled_datestring
  • timezonestring
  • repeat_everystring

    dayweekmonth

  • repeat_timesstring

Responses

200 Per-platform results, or a request_id when it runs in the background

{
  "success": true,
  "request_id": "string"
}

202 Scheduled

{
  "success": true,
  "job_id": "string",
  "request_id": "string",
  "scheduled_date": "string"
}

400 Invalid request

{
  "success": false,
  "message": "string",
  "error": "string",
  "error_code": "string"
}

Something unclear or missing? Write to [email protected] and we’ll fix the page.