Create posts · Robopost Docs

Create posts

On this page

POST /v1/scheduled_posts creates one post per channel you list, all with the same content, scheduled for the same time. You get back every post's ID and its full record.

You need: an API key and the IDs of the channels to post to (GET /v1/channels).

Schedule a post

curl -X POST https://public-api.robopost.app/v1/scheduled_posts \
  -H "Authorization: Bearer $ROBOPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: launch-2026-11-20-facebook-linkedin" \
  -d '{
    "text": "We just launched! https://example.com/launch",
    "channel_ids": ["<facebook channel id>", "<linkedin channel id>"],
    "image_object_ids": ["<media id>"],
    "schedule_at": "2026-11-20T15:00:00Z"
  }'

The response holds one entry per channel:

{
  "scheduled_posts": [ { "id": "8c1f…", "channel_ids": ["<facebook channel id>"], "…": "…" } ],
  "posts": [
    {
      "id": "8c1f…",
      "revision": 2,
      "status": "scheduled",
      "channel_id": "<facebook channel id>",
      "social_network": "FACEBOOK",
      "schedule_at": "2026-11-20T15:00:00.000Z",
      "media": { "ready": true, "image_object_ids": ["<media id>"], "…": "…" },
      "…": "…"
    }
  ]
}

posts is the full record described in List and read posts; keep each id to follow the post. scheduled_posts is the older, shorter shape, kept for existing integrations.

Tip

always send an Idempotency-Key. If the connection drops before you get the answer, send the same request again with the same key: you get the original result instead of duplicate posts. See Idempotency.

Add media

Use media from the team's library, or let Robopost download it from a public URL:

Field What to send
image_object_ids IDs returned by media upload or found in the media library
video_object_id One video ID
gif_object_id One GIF ID
image_urls, video_url, gif_url Public URLs pointing straight at the file

With URLs, posts start in status preparing_media while Robopost downloads the files, then move to scheduled. If a download fails, the post becomes failed with code MEDIA_DOWNLOAD_FAILED and the reason; it is never silently dropped. Media IDs from another team are refused with MEDIA_NOT_FOUND.

Set network options

Each network has its own optional settings object. Send only the ones you need:

{
  "text": "Behind the scenes",
  "channel_ids": ["<youtube channel id>", "<tiktok channel id>"],
  "video_object_id": "<video id>",
  "schedule_at": "2026-11-20T19:00:00Z",
  "youtube_settings": { "videoTitle": "Behind the scenes", "videoType": "short", "videoPrivacyStatus": "public" },
  "tiktok_settings": { "title": "Behind the scenes", "privacyLevel": "PUBLIC_TO_EVERYONE" },
  "first_comment": "Full video on our channel",
  "made_with_ai": false
}
Object Common fields
youtube_settings videoTitle, videoDescription, videoType (video or short), videoPrivacyStatus, selfDeclaredMadeForKids
tiktok_settings title, privacyLevel, disableComment, disableDuet, disableStitch, autoAddMusic
instagram_settings postType, locationId
facebook_settings postType
pinterest_settings pinTitle, destinationLink
wordpress_settings postTitle, postText, postSlug, postType, postCategories, postTags
gmb_settings postTopicType, offer and event fields

The OpenAPI description (/openapi.json) lists every field and its allowed values. first_comment posts a comment under the post right after it publishes, on networks that support it. made_with_ai sets the network's AI label where the network allows apps to (TikTok and X).

Post now, draft or collection

  • Publish as soon as possible: set schedule_at to the current time or earlier.
  • Draft: "is_draft": true. One draft is created for all the channels listed; it isn't published. A single-channel draft can be scheduled later with PATCH.
  • Collection post: "post_collection_id": "<id>" adds the post to an evergreen collection instead of scheduling it.

Repeat a post

{ "is_recur": true, "recur_interval": "WEEKLY", "recur_until_dt_enabled": true, "recur_until_dt": "2027-03-01T00:00:00Z" }

recur_interval is one of EVERY_3_HOURS, EVERY_6_HOURS, BI_DAILY, DAILY, WEEKLY, MONTHLY, DAILY_SPECIFIC_TIME_SLOTS (with daily_recur_interval_time_slots, for example ["09:00", "18:00"]) or WEEKLY_SPECIFIC_TIME_SLOTS (with weekly_recur_interval_time_slots). Each repetition is a new post.

When creation is refused

Status and code Fix
400 CHANNEL_NOT_FOUND The channel ID isn't one of this team's live channels
400 CHANNEL_IDS_REQUIRED List at least one channel, or set is_draft
400 MEDIA_NOT_FOUND A media ID isn't in this team's library
409 PLAN_LIMIT_HIT The plan's scheduled-post limit is reached
409 ACCOUNT_USAGE_FROZEN The subscription isn't active
422 The body doesn't match the schema; detail says which field

Next

List and read posts