DocumentationOpen the app

HTTP

REST API

Your posts, files, queue and routines over plain HTTP, for your own scripts and content pipelines. For an AI agent, the MCP server does the same and more.

Authentication

Create a key in Settings, then API & MCP. It starts with sp_ and is shown once. Send it with every request:

Header
Authorization: Bearer sp_your_key

Endpoints

EndpointWhat it does
GET /api/v1/phonesYour iPhones (their id is the deviceID of a post)
GET /api/v1/accountsYour accounts, with the iPhone each one is on
POST /api/v1/assetsReserves a file upload, then PUT its bytes
GET /api/v1/assetsYour files
POST /api/v1/jobsQueues a post
GET /api/v1/jobsThe 200 latest tasks
DELETE /api/v1/jobs/{id}Cancels a task that has not started
GET /api/v1/summary?hours=24What each iPhone posted over the last hours
GET · POST · PATCH · DELETE /api/v1/schedulesRoutines: a post again and again, with a random start window

Upload a file

Two steps: reserve the upload with the file's size and SHA-256, then send its bytes to the address you get back. 25 MB at most: JPEG, PNG, WebP, HEIC, MP4 or MOV.

Terminal
FILE=slide-1.jpg
SIZE=$(wc -c < "$FILE" | tr -d ' ')
SHA=$(shasum -a 256 "$FILE" | cut -d' ' -f1)

curl -s https://pilot-relay.darvens485.workers.dev/api/v1/assets \
  -H "Authorization: Bearer $SWIPE_PILOT_KEY" -H "Content-Type: application/json" \
  -d "$(printf '{"name":"%s","size":%s,"sha256":"%s","mime":"image/jpeg","kind":"photo"}' "$FILE" "$SIZE" "$SHA")"
# → {"id":"…","uploadURL":"/api/v1/assets/…/content"}

curl -s -X PUT https://pilot-relay.darvens485.workers.dev/api/v1/assets/ASSET_ID/content \
  -H "Authorization: Bearer $SWIPE_PILOT_KEY" --data-binary @"$FILE"
# → {"ok":true}

Queue a post

Give the iPhone's id as deviceID, the files in slide order, and a time in Unix seconds (left out: as soon as the iPhone is free). The idempotency-key header is required: sending the same key again never queues a second post.

Terminal
curl -s https://pilot-relay.darvens485.workers.dev/api/v1/jobs \
  -H "Authorization: Bearer $SWIPE_PILOT_KEY" -H "Content-Type: application/json" \
  -H "idempotency-key: $(uuidgen)" \
  -d '{
    "deviceID": "IPHONE_ID",
    "action": "post",
    "name": "Morning slideshow",
    "assetIDs": ["ASSET_ID_1", "ASSET_ID_2"],
    "caption": "Three things nobody tells you about…",
    "account": "mybrand",
    "scheduledAt": 1792411200
  }'
# → {"ok":true,"id":"TASK_ID","runID":null}
The iPhone must have finished its setup and have a post command, and its queue holds 100 tasks at most. Otherwise the answer says why, with a 409.

Follow it

GET /api/v1/jobs gives each task with its state: finished once the iPhone confirmed the end of the post script. A task with cancelled true and state finished failed on the iPhone. GET /api/v1/summary counts, per iPhone and account, what was confirmed over the last 24 hours (or ?hours= up to 168).

Routines

A routine queues the same post again and again. intervalSeconds is at least an hour; windowSeconds (up to six hours, shorter than the interval) starts each run at a random moment after its time. The iPhone's gap between tasks then keeps its accounts apart.

Terminal
curl -s https://pilot-relay.darvens485.workers.dev/api/v1/schedules \
  -H "Authorization: Bearer $SWIPE_PILOT_KEY" -H "Content-Type: application/json" \
  -d '{
    "deviceID": "IPHONE_ID",
    "name": "Daily slideshow",
    "nextAt": 1792411200,
    "intervalSeconds": 86400,
    "windowSeconds": 1800,
    "template": { "action": "post", "assetIDs": ["ASSET_ID"], "caption": "…", "account": "mybrand" }
  }'

Errors and limits

Errors come back as {"error": "…"} with an HTTP status that says what went wrong: 400 for a field, 401 for the key, 403 for something a key cannot do, 404, 409 for a state that refuses it, 413 when your storage is full. Requests are limited to 120 a minute; above that you get a 429 with retry-after: 60.