Skip to content

Cross-post one file

The most common job: one finished video, every network, the right text and settings for each. One POST /posts with several targets does it - the server expands the request into one post per account, applies the network’s own fields from perPlatform and the network’s own text from overrides, and checks each against that network’s limits in the plan.

  • A paid plan and an API key with write.
  • One connected account per network you want; the ids from GET /accounts. TikTok joins the list when its connector ships.
  • A vertical video (9:16) if Instagram Reels or Facebook Reels are among the targets - a landscape video shows there with bars, which the plan marks as a warning, not a refusal.
  1. GET /accounts → the four account ids.
  2. Upload the file once → mediaId.
  3. One POST /posts/plan with all four targets, overrides and perPlatform.
  4. Read the four rows; fix any ok: false; POST /posts with confirm: true.
  5. GET /posts/{id} for each returned post until live or failed.
Terminal window
export KEY="ds_live_xxxxxxxxxxxxxxxxxxxx"
export API="https://api.dropslate.top/v1"
AUTH="Authorization: Bearer $KEY"
# 1) Account ids by network - never typed by hand
ACCOUNTS=$(curl -s "$API/accounts" -H "$AUTH")
ID_YT=$(echo "$ACCOUNTS" | jq -r '.accounts[] | select(.platform=="youtube") | .id')
ID_IG=$(echo "$ACCOUNTS" | jq -r '.accounts[] | select(.platform=="instagram") | .id')
ID_FB=$(echo "$ACCOUNTS" | jq -r '.accounts[] | select(.platform=="facebook") | .id')
ID_TH=$(echo "$ACCOUNTS" | jq -r '.accounts[] | select(.platform=="threads") | .id')
# 2) Upload once (see the weekly recipe for the upload function)
MEDIA_ID=$(upload ./launch.mp4)
# 3) One body for every network
cat > body.json <<EOF
{
"targets": { "accountIds": ["$ID_YT", "$ID_IG", "$ID_FB", "$ID_TH"] },
"mediaIds": ["$MEDIA_ID"],
"title": "How we schedule a week of posts in ten minutes",
"text": "Full description with timestamps.\n0:00 Intro\n1:20 Upload\n3:05 Plan and confirm",
"tags": ["scheduling", "dropslate"],
"when": { "publishAt": "2026-09-29T18:00", "timezone": "Europe/Kiev" },
"overrides": {
"threads": { "text": "A week of posts in ten minutes. New video." },
"facebook": { "text": "New video: a week of posts in ten minutes." }
},
"perPlatform": {
"youtube": { "visibility": "public", "category": "27", "notifySubscribers": true },
"instagram": { "contentType": "reel", "coverMs": 2500, "shareToFeed": true },
"facebook": { "contentType": "reel" },
"threads": { "topicTag": "Scheduling" }
}
}
EOF
curl -s -X POST "$API/posts/plan" -H "$AUTH" -H "Content-Type: application/json" -d @body.json | jq -r .table

The plan prints one row per account:

account network time check
What We Made youtube 29 Sep, 18:00 (Kyiv) ok
@whatwemade instagram 29 Sep, 18:00 (Kyiv) ok
What We Made Page facebook 29 Sep, 18:00 (Kyiv) ok
@whatwemade threads 29 Sep, 18:00 (Kyiv) ok

Every row ok? Create:

Terminal window
jq '. + {confirm:true}' body.json | curl -s -X POST "$API/posts" -H "$AUTH" -H "Content-Type: application/json" -d @- | jq -r '.posts[] | "\(.id) \(.statusLine)"'

Poll each id until it leaves queued:

Terminal window
curl -s "$API/posts/$POST_ID" -H "$AUTH" | jq '{status, externalUrl, error}'

live posts carry externalUrl; a failed one carries error.code, error.message (the network’s words) and error.hint.

  • Text-only on Facebook and Threads alongside the video elsewhere is two requests: mediaIds applies to every target in one request.
  • A group instead of ids. "targets":{"groupId":"grp_…"} - the same expansion, one line shorter.
  • A different time per network. One request has one when; send one request per time.
  • Over MCP. Say what you want to Claude; it runs the same calls and shows the same table before creating anything - Use cases.