API Overview
The Octopost REST API: base URL, authentication, request format, rate limits and response conventions for posting to social networks from code.
Network status (2026-11): X (
bluesky), Mastodon (mastodon) and LinkedIn (threads) opens after Meta approves the Octopost app. Instagram, Facebook, TikTok, YouTube, Pinterest and Reddit are in platform review and not available yet. Discord, Slack and Telegram are not supported.
The Octopost REST API lets you create, schedule, queue and publish posts, manage the queue, read your connected accounts, save publishing presets and register webhooks. Octopost handles each network's auth, uploads and threading. You send your content once.
The same features are available to AI agents as an MCP server at https://octopost.ink/mcp (see Agents). A machine-readable OpenAPI 3.1 spec lives at https://octopost.ink/openapi.json.
Base URL#
https://octopost.ink/apiThere is no version segment in the path. Paths in these docs are relative to https://octopost.ink, for example POST /api/posts.
Authentication#
Send your API key on every request, either as a Bearer token or in x-api-key:
Authorization: Bearer op_your_api_key_here
# or
x-api-key: op_your_api_key_hereYour keys are at https://octopost.ink/dashboard/api/keys. See Authentication for the details.
Request format#
- JSON bodies with
Content-Type: application/json. POST /api/postsandPUT /api/posts/{id}also acceptmultipart/form-data, so you can upload image and video files directly. See Uploading files.- Field names are camelCase (
scheduledFor,mediaUrls,queueStatus). On the JSON body ofPOST /api/postsandPUT /api/posts/{id}Octopost also accepts the snake_case forms (scheduled_for,media_urls,queue_status, and so on). Other endpoints accept camelCase only and ignore unknown fields. - Times are ISO 8601 strings. Wherever you send a time, include a timezone offset (
2026-04-20T21:00:00Zor2026-04-20T16:00:00-05:00). A time without an offset is rejected.
Response format#
Every successful JSON response has "success": true plus the resource, for example { "success": true, "post": { ... } }.
Errors have an error string and sometimes details. See Errors.
A few things to know when reading responses:
- Fields come back in camelCase (
scheduledFor,platformPostIds,createdAt). - Booleans are
true/false(published,activeon webhooks,enabledin queue settings). Before 2026-11-04 some came back as0/1. - A body that isn't valid JSON, or an upload that is too big or not a supported image/video, is a
400. - Per-network results use the network's display name in
platform("Twitter","LinkedIn"), while stored per-network data (platformPostIds) is keyed by the lowercase id (twitter,linkedin).
Quick example#
Publish a post to X right away:
curl -X POST https://octopost.ink/api/posts \
-H "Authorization: Bearer op_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"content": "Hello from the Octopost API!",
"platforms": ["twitter"],
"published": true
}'{
"success": true,
"status": "published",
"summary": "Published to X.",
"post": {
"id": "6f1c2d3e-...",
"content": "Hello from the Octopost API!",
"platforms": ["twitter"],
"published": true,
"status": "published",
"platformPostIds": {
"twitter": { "id": "1234567890", "url": "https://x.com/you/status/1234567890" }
}
},
"results": {
"twitter": { "platform": "twitter", "status": "published", "postId": "1234567890", "url": "https://x.com/you/status/1234567890" }
},
"publishResults": [
{ "platform": "Twitter", "success": true, "postId": "1234567890", "postUrl": "https://x.com/you/status/1234567890" }
],
"warnings": []
}The status is 201 when every network has it and 207 when one didn't (status is then partial or failed; results says why). A publish still running after about 20 seconds (Threads with media can take minutes) answers 202 with "status": "publishing" and the post id; it carries on, and you poll GET /api/posts/{id} until the status changes (details). Send an Idempotency-Key header so a retried request can't post twice. Leave out published to save a draft, then publish it later with POST /api/posts/{id}/publish.
Rate limits#
| Bucket | Limit |
|---|---|
Most /api/* requests | 100 per minute |
POST /api/posts/{id}/publish | 50 per hour |
Limits are counted per client IP address. Going over returns 429 with a Retry-After header. See Rate Limits.
Resources#
- Authentication: API keys
- Posts: create, schedule, queue, publish, retry, calendar, bulk scheduling and failed posts
- Accounts: connected social accounts
- Presets: saved platform selections
- Webhooks: get notified when a post publishes or fails
- Analytics: likes, reposts, replies and X views for published posts
- Rate Limits
- Errors