Skip to main content

Upload Photos

Upload photos (and mixed media for supported platforms) to various social media platforms using this endpoint.

Endpoint

POST /api/upload_photos

Headers

NameValueDescription
AuthorizationApikey your-api-key-hereYour API key for authentication

Common Parameters

NameTypeRequiredDescription
userStringYesUser identifier
platform[]ArrayYesPlatform(s) to upload to. Supported values: tiktok, instagram, linkedin, facebook, x, threads, pinterest, bluesky, reddit, google_business
photos[]ArrayYesArray of files to upload. Accepts photos (jpg, png, etc.).
Note: You can also include videos (mp4, mov, etc.) ONLY for Instagram and Threads mixed carousels.
titleStringConditionalDefault title/caption of the post. Required for Reddit. Optional for all other platforms (TikTok, Instagram, Facebook, LinkedIn, X, Threads, Bluesky, Pinterest).
descriptionStringNoOptional extended text used on TikTok photo descriptions, LinkedIn commentary, Facebook descriptions, Pinterest notes, and Reddit bodies. Ignored elsewhere.
scheduled_dateString (ISO-8601)NoOptional date/time (ISO-8601) to schedule publishing, e.g., "2024-12-31T23:45:00Z". Must be in the future (≤ 365 days). Omit for immediate upload.
timezoneString (IANA)NoOptional timezone identifier (e.g., "Europe/Madrid", "America/New_York"). If provided, scheduled_date is interpreted in this timezone. Defaults to UTC if omitted. See IANA Time Zone Database for valid values.
async_uploadBooleanNoIf true, the request returns immediately with a request_id and processes in the background. See Upload Status.
add_to_queueBooleanNoIf true, automatically schedules the post to your next available queue slot. Cannot be used with scheduled_date. See Queue System.
max_posts_per_slotIntegerNoOverride the profile's max posts per slot setting for this request. Only used when add_to_queue=true. See Queue System.
first_commentStringNoAutomatically post a first comment after publishing. Supported on Instagram, Facebook, Threads, Bluesky, Reddit, X, and YouTube. On X (Twitter) and Threads, this creates a reply to the main post. For X threads, the comment is posted as a reply to the last tweet in the thread. On YouTube, it posts as a top-level comment on the video.

Important: If you set async_upload to false but the upload takes longer than 59 seconds, it will automatically switch to asynchronous processing to avoid timeouts. In that case, use the request_id with the Upload Status endpoint to check the upload status and result.

Platform-Specific First Comments

The first_comment parameter serves as a fallback. To set a custom first comment for a particular platform, use the optional [platform]_first_comment parameter. If provided, it will override the main first_comment for that platform.

Example Optional Parameters:

  • instagram_first_comment: "Follow for more content! #photography"
  • facebook_first_comment: "Let me know your thoughts in the comments!"
  • x_first_comment: "Thread incoming! 🧵"
  • threads_first_comment: "First comment on Threads!"
  • reddit_first_comment: "Source in the comments."
  • bluesky_first_comment: "More details in the replies."

Scheduling behavior: When you provide scheduled_date, the API responds with 202 Accepted and includes a job_id. That same job_id will later appear in Upload History to correlate the scheduled job with the publish record. You can also use the job_id with the Upload Status endpoint to check the execution status of the scheduled post.

Video Support (Mixed Carousels):

  • Instagram & Threads: You can upload videos in the photos[] array to create mixed carousels (photos + videos).
  • All other platforms (Facebook, TikTok, LinkedIn, X, Pinterest): Do NOT upload videos to this endpoint. Use the Upload Video endpoint instead. Uploading videos here for these platforms will result in an error.

Platform-Specific Titles

The title parameter serves as a fallback. To set a custom title for a particular platform, use the optional [platform]_title parameter. If provided, it will override the main title for that platform.

Example Optional Parameters:

  • instagram_title: "Check out my latest reel on Instagram! #reels"
  • facebook_title: "Excited to share this new video with my Facebook friends and family."
  • tiktok_title: "New TikTok video just dropped! 🔥"
  • linkedin_title: "A professional insight on the latest industry trends, discussed in this video."
  • x_title: "New video out now! 📢"

Platform-Specific Parameters

LinkedIn

NameTypeRequiredDescriptionDefault
linkedin_titleStringNoSpecific title for the LinkedIn post. Fallbacks to title.title
linkedin_description or descriptionStringNoSent as the post commentary. If omitted, we reuse title.title
visibilityStringNoVisibility setting for the post (accepted value: "PUBLIC")PUBLIC
target_linkedin_page_idStringNoLinkedIn page ID to upload photos to an organization"107579166"

Facebook

NameTypeRequiredDescriptionDefault
facebook_titleStringNoSpecific title for the Facebook post. Fallbacks to title.title
facebook_page_idStringYesFacebook Page ID where the photos will be posted-
facebook_media_typeStringNoType of media ("POSTS" or "STORIES")"POSTS"

Note: The caption is applied only to the first photo uploaded. For correct posting on Facebook, ensure the Page is directly associated with your personal profile and not managed through a Business Portfolio.

Note: If facebook_page_id is not provided, we will automatically use the user's only connected Page (if exactly one exists). If multiple Pages are connected, the API returns a helpful error with an available_pages list so you can choose one. Posting to personal Facebook profiles via API is not supported by Meta; only Pages can be posted to.

X (Twitter)

NameTypeRequiredDescriptionDefault
x_titleStringNoSpecific title for the tweet. Fallbacks to title.title
x_long_text_as_postBooleanNoWhen true, publishes long text as a single post. Otherwise, creates a thread.false
x_thread_image_layoutStringNoComma-separated list of how many images to attach to each tweet in the thread. Each value must be 1-4, and the total must equal the number of images. Example: "4,4" puts 4 images in each of 2 tweets; "2,3,1" puts 2 in the first, 3 in the second, 1 in the third. If omitted and more than 4 images are provided, defaults to auto-chunking into groups of 4.auto
reply_settingsStringNoControls who can reply to the tweet ("following", "mentionedUsers", "subscribers", "verified")-
geo_place_idStringNoPlace ID for adding geographic location to the tweet-
nullcastBooleanNoWhether to publish without broadcasting (promotional/promoted-only posts)false
for_super_followers_onlyBooleanNoTweet exclusive for super followersfalse
community_idStringNoCommunity ID for posting to specific communities-
share_with_followersBooleanNoShare community post with followersfalse
direct_message_deep_linkStringNoLink to take the conversation from public timeline to private Direct Message-
tagged_user_idsArrayNoArray of user IDs to tag in the photos (max 10 users)[]
reply_to_idStringNoID of the tweet to reply to. Creates a reply to the specified tweet.-
exclude_reply_user_idsArrayNoArray of user IDs to exclude from replying to this tweet. Requires reply_to_id.[]

Note: For Twitter uploads, specify the platform as "x" in the platform[] array.

More than 4 images: X supports a maximum of 4 images per tweet. If you provide more than 4 images, the API will automatically create a thread, distributing images across multiple tweets (up to 4 images each). Use x_thread_image_layout to control exactly how images are distributed across tweets.

The global description field is ignored for X photo uploads.

How X (Twitter) Thread Creation Works (Advanced Logic)

Note: The following describes the default thread creation logic. To override this and post long text as a single post, set the x_long_text_as_post parameter to true.

The system is engineered to create well-formatted, natural-looking threads on X (formerly Twitter). Instead of simply splitting text at every line break, it intelligently groups paragraphs to create more readable tweets.

Here's the step-by-step logic:

Intelligent Paragraph Grouping (Primary Method):

The function first identifies distinct paragraphs (any text separated by a blank line). It then combines as many of these paragraphs as possible into a single tweet, filling it up to the 280-character limit without exceeding it. The double newline (\n\n) between combined paragraphs is preserved for formatting. This results in fewer, more substantial tweets that flow naturally, just as if a person had written them.

Handling Exceptionally Long Paragraphs:

If a single paragraph is, by itself, longer than the 280-character limit, a more granular splitting logic is automatically triggered for that paragraph only:

  • Split by Line Break: The system first attempts to break the paragraph down by its individual line breaks (\n).
  • Split by Word: If any of those single lines are still too long, it will split them by words as a final resort.

Media Attachment:

Images are distributed across tweets according to the x_thread_image_layout parameter. If not specified and more than 4 images are provided, they are automatically distributed in groups of 4. Text parts and image chunks are interleaved across the thread tweets.

TikTok

NameTypeRequiredDescriptionDefault
tiktok_titleStringNoSpecific title for the TikTok post (max 90 characters). Fallbacks to title.title
post_modeStringNoControls how the upload is handled. DIRECT_POST publishes immediately; MEDIA_UPLOAD sends the media to the TikTok inbox so users can finish editing in-app.DIRECT_POST
privacy_levelStringNoAccepted values: PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY.PUBLIC_TO_EVERYONE
auto_add_musicBooleanNoAutomatically add background music to photosfalse
disable_commentBooleanNoDisable comments on the postfalse
brand_content_toggleBooleanNoSet to true for paid partnerships that promote third-party brands.false
brand_organic_toggleBooleanNoSet to true when promoting the creator's own business.false
photo_cover_indexIntegerNoIndex (starting at 0) of the photo to use as the cover/thumbnail for the TikTok photo post0
tiktok_description or descriptionStringNoFor photo posts, used as description inside post_info (max 4,000 characters).title

Note on Draft Mode (MEDIA_UPLOAD): When using MEDIA_UPLOAD mode (Draft), TikTok does not allow setting a title, caption, privacy settings, or other metadata via the API. The video is simply uploaded to your TikTok inbox/drafts, and you must add the title, caption, and settings manually within the TikTok app before publishing.

Instagram

NameTypeRequiredDescriptionDefault
instagram_titleStringNoSpecific title for the Instagram post. Fallbacks to title.title
media_typeStringNoType of media ("IMAGE" or "STORIES"). Automatically handles CAROUSEL/REELS logic if mixed media is detected."IMAGE"
collaboratorsStringNoComma-separated list of collaborator usernames.-
user_tagsStringNoComma-separated list of users to tag (e.g., "@user1, user2").-
location_idStringNoInstagram location ID.-

The global description field is ignored for Instagram uploads (title serves as caption).

Threads

NameTypeRequiredDescriptionDefault
threads_titleStringNoSpecific title for the Threads post. Fallbacks to title.title
threads_thread_media_layoutStringNoComma-separated list of how many media items to include in each Threads post. Each value must be 1-10, and the total must equal the number of files. Example: "5,5" splits 10 items into 2 posts of 5 each; "3,4,3" splits 10 items into 3 posts. If omitted and more than 10 items are provided, defaults to auto-chunking into groups of 10.auto

More than 10 items: Threads supports a maximum of 10 media items per post (carousel). If you provide more than 10 items, the API will automatically create multiple posts, distributing media across posts (up to 10 items each). Use threads_thread_media_layout to control exactly how media items are distributed across posts.

The global description field is ignored for Threads photo uploads.

Pinterest

NameTypeRequiredDescriptionDefault
pinterest_titleStringNoSpecific title for the Pinterest Pin. Fallbacks to title.title
pinterest_description or descriptionStringNoPopulates the Pin description. If omitted, we reuse title.title
pinterest_board_idStringYesPinterest board ID to publish the photo to.-
pinterest_alt_textStringNoAlt text for the image.-
pinterest_linkStringNoDestination link for the photo Pin.-

Bluesky

NameTypeRequiredDescriptionDefault
bluesky_titleStringNoSpecific text for the Bluesky post. Fallbacks to title.title

Note: Bluesky supports up to 4 images per post.

Reddit

NameTypeRequiredDescriptionDefault
reddit_titleStringNoSpecific title for the Reddit post. Fallbacks to title.title
subredditStringYesName of the subreddit to post to (without "r/").-
flair_idStringNoID of the flair to apply to the post.-

Note: Reddit photo posts support a single image. The image will be uploaded as a native Reddit image post.

Google Business Profile

NameTypeRequiredDescriptionDefault
gbp_topic_typeStringNoPost type: STANDARD (default), EVENT, or OFFER.STANDARD
gbp_cta_typeStringNoCall-to-action button: BOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP, CALL.-
gbp_cta_urlStringConditionalURL for the CTA button. Required if gbp_cta_type is set.-

Event parameters (when gbp_topic_type is EVENT):

NameTypeRequiredDescription
gbp_event_titleStringYesTitle of the event.
gbp_event_start_dateStringYesStart date in YYYY-MM-DD format.
gbp_event_start_timeStringNoStart time in HH:MM format (24h).
gbp_event_end_dateStringYesEnd date in YYYY-MM-DD format.
gbp_event_end_timeStringNoEnd time in HH:MM format (24h).

Offer parameters (when gbp_topic_type is OFFER):

NameTypeRequiredDescription
gbp_coupon_codeStringNoCoupon or promo code.
gbp_redeem_urlStringNoURL where the offer can be redeemed.
gbp_termsStringNoTerms and conditions of the offer.

Example Requests

curl \
-H 'Authorization: Apikey your-api-key-here' \
-F 'photos[]=@/path/to/image.jpg' \
-F 'photos[]=@/path/to/video.mp4' \
-F 'user="test"' \
-F 'platform[]=instagram' \
-F 'title="My Mixed Carousel"' \
-X POST https://api.upload-post.com/api/upload_photos

Upload Photos to Facebook

curl \
-H 'Authorization: Apikey your-api-key-here' \
-F 'photos[]=@/path/to/image1.jpg' \
-F 'photos[]=@/path/to/image2.jpg' \
-F 'user="test"' \
-F 'platform[]=facebook' \
-F 'facebook_page_id="123456789"' \
-F 'title="My Photo Album"' \
-X POST https://api.upload-post.com/api/upload_photos

Upload Photo to Reddit

curl \
-H 'Authorization: Apikey your-api-key-here' \
-F 'photos[]=@/path/to/image.jpg' \
-F 'user="test"' \
-F 'platform[]=reddit' \
-F 'subreddit="pics"' \
-F 'title="Check out this photo!"' \
-X POST https://api.upload-post.com/api/upload_photos

Responses

  • 200 OK (synchronous, finished fast)
{
"success": true,
"results": {
"instagram": { "success": true, "url": "https://instagram.com/p/...", "photos_were_processed": true, "changes_per_image": [ {} ] },
"reddit": { "success": false, "error": "Subreddit is required for photo posts to Reddit." }
},
"usage": { "count": 13, "limit": 100, "last_reset": "..." }
}
  • 200 OK (asynchronous/background started or sync→background fallback)
{
"success": true,
"message": "Upload initiated successfully in background.",
"request_id": "1a2b3c4d5e...",
"total_platforms": 2
}
  • 202 Accepted (scheduled)
{
"success": true,
"job_id": "scheduler_job_456",
"scheduled_date": "2025-09-22T10:00:00Z"
}
  • 400 Bad Request

    • Missing user, platform[], Pinterest without pinterest_board_id, Reddit without subreddit, invalid platforms, invalid scheduled_date.
  • 401 Unauthorized: { "success": false, "message": "Invalid or expired token" }

  • 403 Forbidden (plan restrictions)

  • 404 Not Found (e.g., user not found)

  • 429 Too Many Requests (monthly limit exceeded; includes current usage)

{
"success": false,
"message": "This upload would exceed your monthly limit.",
"usage": { "count": 10, "limit": 10, "last_reset": "..." }
}
  • 500 Internal Server Error: { "success": false, "error": "Detailed error message" }

Notes

  • When async or when sync falls back to background, use GET /api/uploadposts/status?request_id={request_id} to poll progress.
  • Per-platform results may include fields like url, post_id(s), and platform-specific metadata or error.