Post from your own code

A small REST API over the same pipeline the app uses — including the pre-flight checks and the per-network delivery isolation. JSON in, JSON out, bearer auth.

One request shape covers all 11 networks we support. 5 publish for anyone today, the rest are clearing each platform's review — the status page says exactly which, and your integration does not change as they clear.

Authentication

Create a key in the app under API keys. It is shown once — we store only a hash, so it cannot be recovered afterwards. Send it as a bearer token.

Authorization: Bearer pilot_your_key_here

Endpoints

GET/api/v1/accountsThe accounts this key can post to.
GET/api/v1/postsRecent posts and where each one landed, per network.
POST/api/v1/mediaUpload an image or video — multipart or by URL — and get an id back.
POST/api/v1/postsCreate a post — queue it, schedule it, or publish immediately.

Upload media, get an id back

Most posts carry an image or a video. Upload it once to /api/v1/media and attach the returned id to any post. When the bytes are on your machine, send multipart form-data:

curl -X POST https://attentionpilot.com/api/v1/media \
  -H "Authorization: Bearer $PILOT_API_KEY" \
  -F "[email protected]"

When the file is already hosted somewhere — the common case for an agent that just generated an image — send JSON with a url instead and we fetch it:

curl -X POST https://attentionpilot.com/api/v1/media \
  -H "Authorization: Bearer $PILOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://cdn.example.com/launch.jpg"}'

Both return 201 with the stored file. filename, width, height and durationMs are optional on either path — send them if you already know them, skip them if you don't.

{
  "media": {
    "id": "9b2e…",
    "filename": "launch.jpg",
    "kind": "image",
    "mime": "image/jpeg",
    "size": 184320,
    "width": null, "height": null, "durationMs": null
  }
}

Post to every network

Attach media ids with media — the order you list them is the carousel order. Omit schedule and it drops into your next free queue slot. Pass "now" to publish immediately, or an ISO timestamp for a specific time.

curl -X POST https://attentionpilot.com/api/v1/posts \
  -H "Authorization: Bearer $PILOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "caption": "We shipped per-network retries today.",
    "media": ["9b2e…"],
    "accounts": "all"
  }'

On some networks media is not optional: Instagram, TikTok and Pinterest will not accept a text-only post at all, and YouTube needs a video. Target one of them without the right attachment and pre-flight rejects the request with a 422 naming the network — before anything is scheduled.

Pick networks by name

accounts takes account ids, platform names, or handles — whichever you have to hand.

{
  "caption": "Short version for the fast networks.",
  "accounts": ["x", "bluesky", "threads"],
  "schedule": "2026-08-01T09:00:00Z"
}

What comes back

Publishing immediately returns the per-network outcome, because each network succeeds or fails on its own. A partly-published post is a normal result, not an error.

{
  "id": "0f3c…",
  "status": "partial",
  "targets": [
    { "platform": "bluesky", "status": "posted",
      "url": "https://bsky.app/profile/you/post/3k…" },
    { "platform": "x", "status": "failed",
      "error": "312 chars — X allows 280." }
  ]
}

Errors worth handling

400Bad body, unknown accounts, or an unparseable schedule.
401The key is missing, malformed or revoked.
402The workspace has more connected accounts than its billing covers. Posts are never metered — disconnect an account or add billing, then retry.
422Pre-flight failed — the response lists which network and why.

Live: the same API over MCP

Point Claude or any MCP client at https://attentionpilot.com/api/mcp with your key as a bearer token and the agent gets the same capabilities — list accounts, add media, create a post, read back the delivery. Setup takes one config block.

Posting is an API call. Make one.

Start free

One account free. No card.