Uploader DocsAPIFAQAbout Privacy Sign in

API reference

Publish from your own script, bot or agent

Everything the composer does is available over HTTP. Create a key in your dashboard, and one call publishes to as many of your connected accounts as you like.

Base URL

Every path below is relative to your Uploader host. All traffic is HTTPS.

https://uploader.stapilo.com

Authentication

Create a key under API keys in your dashboard. It is shown once, when it is created, and stored only as a hash — if you lose it, revoke it and make another. A key acts as you: anything done with it counts as done by you, so treat it like a password.

Send it in whichever of these three suits your client:

Authorization: Bearer <your-key>
x-api-key: <your-key>
?key=<your-key>

The query parameter is there for tools that cannot set a header. Prefer a header where you can — URLs end up in logs.

List your accounts

GET /accounts

Returns the accounts you have connected, with the ids you pass to /publish.

curl https://uploader.stapilo.com/accounts \
  -H "Authorization: Bearer $UPLOADER_KEY"
{
  "accounts": [
    {
      "id": "instagram:17841400000000000",
      "platform": "instagram",
      "name": "@yourhandle",
      "connectedAt": "2026-08-01T09:14:22.000Z"
    }
  ]
}

Publish a post

POST /publish

Send text, media, or both. With no accounts field the post goes to every account you have connected.

curl https://uploader.stapilo.com/publish \
  -H "Authorization: Bearer $UPLOADER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Shipped something today.",
    "image": "https://example.com/photo.jpg",
    "accounts": ["instagram:17841400000000000", "x:1466240000000000000"]
  }'

Body fields

Field Type Meaning
accountsstring[] Which accounts to publish to. Omit it and every connected account is used.
textstring The text of the post.
imagestring | string[] Public URL of a photo, or several. Ignored by networks that take no photo.
videostring Public URL of a video.
reelboolean Publish the video as a Reel where the network has them.
storyboolean Publish as a Story where the network has them.
youtubePrivacystring YouTube visibility: public, unlisted or private. Anything else is treated as unlisted.
youtubeTitlestring Title of the YouTube upload, up to 100 characters. Left out, the first line of the text is used.
youtubeDescriptionstring Description of the YouTube upload. Left out, the text is used.

Give at least text or one piece of media, or the call is rejected. Media has to be reachable from the public internet — several networks fetch it themselves rather than accepting an upload.

What comes back

One result per account, in the order they were published, each naming the account and whether it worked.

{
  "results": [
    { "accountId": "instagram:17841400000000000", "platform": "instagram", "ok": true,
      "externalPostId": "17912...", "permalink": "https://www.instagram.com/p/..." },
    { "accountId": "x:1466240000000000000", "platform": "x", "ok": false,
      "error": "X media upload is being added next — text posts work now." }
  ]
}

Status codes

A per-account failure is a 207, not an error: one network being down is not a reason to fail the other ten.

Worth knowing