Quickstart
Five requests take you from a fresh API key to a scheduled post: find out who you are, list the accounts, plan a post, create it, read its status. Every request is https://api.dropslate.top/v1 plus a path, with the key in the Authorization header and JSON bodies. Uploading a file is the one extra step, covered in the working example; this page schedules a text post to keep the flow short.
Before you start
Section titled “Before you start”- A paid plan - the API starts on Creator - and an API key with
write: Settings → API keys → New key, tick Allow creating and publishing posts. The key is shown once. - A connected Facebook Page or Threads profile: both take a post without a file. YouTube and Instagram need media.
curlandjq, or any HTTP client.
-
Set the key. In a shell, not in a file you commit and never in a prompt to an agent:
Terminal window export KEY="ds_live_xxxxxxxxxxxxxxxxxxxx"export API="https://api.dropslate.top/v1" -
Who am I.
GET /whoamianswers with the workspace, its time zone and plan, what the key may do, and this month’s usage.Terminal window curl -s "$API/whoami" -H "Authorization: Bearer $KEY" | jq{"workspace": { "id": "ws_3k9d", "slug": "what-we-made", "name": "What We Made", "plan": "creator", "currency": "USD", "tz": "Europe/Kiev" },"user": { "id": "usr_a1", "name": "Dmytro", "email": null },"credential": { "kind": "api_key", "name": "n8n integration", "scopes": ["read", "write"] },"usage": { "plan": "creator", "period": "2026-09", "posts": { "used": 46, "limit": 200 }, "storage": { "usedBytes": 1288490188, "limitBytes": 16106127360 }, "accounts": { "used": 3, "limit": 6 } }}tzis the zone every time is read in;scopesmust containwritefor the last two steps. -
List the accounts. Account ids come from here and nowhere else.
Terminal window curl -s "$API/accounts" -H "Authorization: Bearer $KEY" | jq '.accounts[] | {id, platform, displayName, status}'{ "id": "acc_fb_7c2e", "platform": "facebook", "displayName": "What We Made", "status": "ok" }{ "id": "acc_th_91af", "platform": "threads", "displayName": "@whatwemade", "status": "ok" }Only an account with
status: "ok"can be published to;expiredorrevokedneeds a person to reconnect it in the dashboard. -
Plan.
POST /posts/plantakes the post and answers with one row per account and a check. It creates nothing.Terminal window cat > post.json <<'EOF'{"targets": { "accountIds": ["acc_fb_7c2e", "acc_th_91af"] },"mediaIds": [],"text": "Office hours today at 18:00 Kyiv. Bring one question.","when": { "publishAt": "2026-09-29T17:00", "timezone": "Europe/Kiev" },"perPlatform": { "facebook": { "contentType": "text", "link": "https://dropslate.top/" }, "threads": { "topicTag": "OfficeHours" } }}EOFcurl -s -X POST "$API/posts/plan" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d @post.json | jq{"ok": true,"status": "queued","rows": [{ "accountId": "acc_fb_7c2e", "platform": "facebook", "publishAt": "2026-09-29T14:00:00.000Z", "ok": true, "issues": [] },{ "accountId": "acc_th_91af", "platform": "threads", "publishAt": "2026-09-29T14:00:00.000Z", "ok": true, "issues": [] }],"quota": { "used": 46, "limit": 200, "requested": 2 },"table": "account network time check\nWhat We Made facebook 29 Sep, 17:00 (Kyiv) ok\n@whatwemade threads 29 Sep, 17:00 (Kyiv) ok"}A row with
ok: falselistsissues-{code, message, hint}each - andokat the top isfalse.tableis the same text an MCP agent shows a person. -
Create. The same body with
confirm: true. Without it the answer is409 confirm_requiredand nothing is created.Terminal window jq '. + {confirm: true}' post.json | curl -s -X POST "$API/posts" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d @- | jq '.posts[] | {id, status, statusLine}'{ "id": "pst_5e1b", "status": "queued", "statusLine": "Queued. Facebook · What We Made · 29 Sep, 17:00 (Kyiv)." }{ "id": "pst_5e1c", "status": "queued", "statusLine": "Queued. Threads · @whatwemade · 29 Sep, 17:00 (Kyiv)." }One post per account; each is
queued.when: "now"sends at once;when: "draft"saves without a time. -
Read the status. After the time,
GET /posts/{id}:Terminal window curl -s "$API/posts/pst_5e1b" -H "Authorization: Bearer $KEY" | jq '{status, externalUrl, error, statusLine}'livecomes withexternalUrl;failedwitherror.code,error.messagein the network’s own words anderror.hint. Those are the only states afterqueued.
What you see next
Section titled “What you see next”The two posts are on the dashboard’s Queue and Calendar like any other, with createdVia: "api" in the drawer. Retry, Cancel and Reschedule work on them there, and the same actions exist as POST /posts/{id}/retry, POST /posts/{id}/cancel and PATCH /posts/{id}.
Common errors
Section titled “Common errors”| Error | Cause | Fix |
|---|---|---|
401 unauthenticated |
The key is missing, mistyped or revoked. | Check Authorization: Bearer ds_live_…; create a new key if it was revoked. |
403 insufficient_scope on POST /posts |
The key has only read. |
Create a key with Allow creating and publishing posts. |
409 confirm_required |
confirm: true missing. |
Add it; nothing was created. |
402 quota_exceeded |
The month’s posts or the plan’s API access. | The body carries limit, used and upgradeUrl. |
404 not_found on an account id |
The id is not in this workspace. | Take ids from GET /accounts. |
429 rate_limited |
600 requests in 10 minutes from this address, or 60 POST /posts in an hour. |
Wait the seconds in Retry-After. |
Related
Section titled “Related”- Working example - the same flow with a file upload and polling, in curl, Node and Python.
- Authentication, Errors, Rate limits
- OpenAPI reference - every field of every route.