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:
Authorization: Bearer sp_your_keyEndpoints
| Endpoint | What it does |
|---|---|
GET /api/v1/phones | Your iPhones (their id is the deviceID of a post) |
GET /api/v1/accounts | Your accounts, with the iPhone each one is on |
POST /api/v1/assets | Reserves a file upload, then PUT its bytes |
GET /api/v1/assets | Your files |
POST /api/v1/jobs | Queues a post |
GET /api/v1/jobs | The 200 latest tasks |
DELETE /api/v1/jobs/{id} | Cancels a task that has not started |
GET /api/v1/summary?hours=24 | What each iPhone posted over the last hours |
GET · POST · PATCH · DELETE /api/v1/schedules | Routines: 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.
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.
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}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.
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.