Agent Integration
Let an AI agent post for you: connect Claude Code, claude.ai, ChatGPT, Cursor or Codex to Octopost by URL and sign in, or call the REST API with a key.
Network status (2026-11): X, Bluesky, Mastodon and LinkedIn (personal profiles) are live. 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, even where older parts of these docs mention them.
Octopost is designed to work well with AI agents. All documentation is available as raw markdown files that agents can fetch and read directly, and the REST API uses straightforward JSON requests that any HTTP-capable agent can call.
Connect an agent (MCP)#
The fastest path is the MCP server at https://octopost.ink/mcp. Add the URL to your client and sign in to Octopost when it asks (OAuth), or send an API key as Authorization: Bearer op_....
| Client | Setup |
|---|---|
| Claude Code | claude mcp add --transport http octopost https://octopost.ink/mcp, then /mcp > octopost > Authenticate |
| claude.ai / Claude Desktop | Customize > Connectors > + Add > Add custom connector, URL https://octopost.ink/mcp, Continue, Sign in now, Add, Allow |
| ChatGPT | Plugins > + > Add custom MCP server, URL https://octopost.ink/mcp, authentication OAuth, Allow |
| Cursor | {"mcpServers": {"octopost": {"url": "https://octopost.ink/mcp"}}} in ~/.cursor/mcp.json, then Connect |
| Codex CLI | codex mcp add octopost --url https://octopost.ink/mcp then codex mcp login octopost |
| VS Code | {"servers": {"octopost": {"type": "http", "url": "https://octopost.ink/mcp"}}} in .vscode/mcp.json |
| API key (any client, CI) | header Authorization: Bearer op_..., e.g. claude mcp add --transport http octopost https://octopost.ink/mcp --header "Authorization: Bearer op_..." |
Full steps per client, Windsurf and Gemini CLI included: MCP docs and the connect pages.
Approvals: queue_post or schedule_post with needs_approval: true holds a post until a person approves it. Octopost emails the account owner (and any approvers) one-tap Approve / Reject / Edit links within about 5 minutes; tell the user to check their email. Agents can't approve their own posts: approve_queued_post is refused unless the owner allowed agent approvals, and never for a post the same key or app made. See Approvals.
Quick Start for Agents#
Every documentation page on Octopost is available as a raw .md file. Agents can fetch these directly to get full API details, platform-specific guides, and usage examples.
Available Documentation URLs#
API Reference:
https://octopost.ink/docs/api/overview.md: API introduction, base URL, auth format, rate limitshttps://octopost.ink/docs/api/authentication.md: API key generation, Bearer token usage, securityhttps://octopost.ink/docs/api/posts.md: Create, read, update, delete, and publish postshttps://octopost.ink/docs/api/accounts.md: List and manage connected social accountshttps://octopost.ink/docs/api/presets.md: Publishing presets for platform groupshttps://octopost.ink/docs/api/webhooks.md: Webhook subscriptions for real-time eventshttps://octopost.ink/docs/api/analytics.md: Likes, reposts, replies and X views for published postshttps://octopost.ink/docs/api/rate-limits.md: Rate limit details and backoff strategieshttps://octopost.ink/docs/api/errors.md: Error codes and handlinghttps://octopost.ink/docs/threading.md: Threaded posts (main + reply chain; use for link-in-reply pattern)
Platform Guides:
https://octopost.ink/docs/platforms/twitter.md: Twitter/X, live (280 chars, images, video, threads, polls)https://octopost.ink/docs/platforms/bluesky.md: Bluesky, live (300 graphemes, app passwords, facets)https://octopost.ink/docs/platforms/linkedin.md: LinkedIn, live for personal profiles (3000 chars, UGC Post API)https://octopost.ink/docs/platforms/mastodon.md: Mastodon, live (per-instance, content warnings, polls)https://octopost.ink/docs/platforms/threads.md: Threads, after Meta approval (500 chars, two-step publish)https://octopost.ink/docs/platforms/instagram.md: Instagram, in platform review (reference only)https://octopost.ink/docs/platforms/facebook.md: Facebook, in platform review (reference only)https://octopost.ink/docs/platforms/tiktok.md: TikTok, in platform review (reference only)https://octopost.ink/docs/platforms/youtube.md: YouTube, in platform review (reference only)
Agent Integration:
https://octopost.ink/docs/agents.md: This pagehttps://octopost.ink/docs/cli.md: Theoctopostcommand line tool (post, schedule, queue, preview from a shell)
Agent Instructions Template#
Copy and paste the following block into your agent's system prompt or instructions to give it everything it needs to use Octopost:
# Octopost API -- Agent Quick Reference
Base URL: https://octopost.ink/api
Auth: Bearer token in Authorization header
## Key Endpoints
POST /posts -- Create a post (saved as a draft unless published or scheduled_for is set)
Body: {
"content": "string",
"platforms": ["twitter"], // live: "twitter", "bluesky", "mastodon", "linkedin". "threads" after Meta approval.
"media_urls": ["https://...", { "url": "...", "alt": "alt text" }], // URL or {url, alt}; mixing is fine
"published": true, // publish now
"scheduled_for": "2027-01-20T09:00:00-06:00", // or schedule: ISO 8601 WITH an offset or Z
"segments": [{ "content": "string", "mediaUrls": ["url", ...] }, ...],
"variants": { "linkedin": { "content": "longer text" } }, // optional: own content/segments/media_urls per network; others get the main post
"first_comment": "string", // optional: posted as a reply (X, Bluesky, Mastodon, Threads) or comment (LinkedIn) right after the post
"accounts": { "twitter": "@handle" }, // optional, when a network has several accounts
"allow_duplicate": true // optional: same text to the same network within 7 days is refused (409) without it
}
// Guardrails for API keys: a per-key daily limit (429 code daily_cap), blocked terms (201 with
// held: true, saved as pending approval, not published), duplicates (409 code duplicate).
POST /posts/preview -- Dry run of POST /posts (same body): counts per network, X units, media checks, problems, warnings. Saves nothing.
POST /media-uploads -- { "filename"?, "size"? } -> one-time upload_url (15 min). PUT the raw file to it
(curl -T ./photo.jpg "<upload_url>", no auth header); the response has media_url for media_urls.
GET /usage -- X units used/left this month, accounts vs plan
// Threading tip: use `segments` to attach a URL as a REPLY instead of
// putting it in the main post. Link posts get algorithmically down-ranked
// on Twitter and Threads; a reply doesn't. Example:
// { "content": "I shipped X", "segments": [{"content": "https://x.com"}] }
GET /posts?limit=20&cursor=... -- List posts newest first; pagination.nextCursor fetches the next page
GET /posts/:id -- Get a single post
PUT /posts/:id -- Update a post (draft or scheduled only)
DEL /posts/:id -- Delete a post
POST /posts/:id/publish -- Publish a draft now (JSON result; add ?stream=1 for progress events)
GET /accounts -- List connected social accounts
GET /presets -- List publishing presets
GET /analytics -- Totals per network + top posts (?from=&to=&platform=&top=)
GET /analytics/:id -- One post's numbers per network, with 1h/24h/7d snapshots
POST /analytics/refresh -- Read fresh numbers now (once every 10 minutes)
POST /webhooks -- Subscribe to events
Body: { "url": "https://...", "events": ["post.published", "post.failed"] }
## Platform Constraints
- twitter (live): 280 chars per post (links count as 23; X Premium long posts not supported), images (4), video (1), threads (up to 24 replies), polls. X units: 1 per plain post, 13 per post with a link.
- bluesky (live): 300 graphemes, images (4, 1MB each), threads
- linkedin (live, personal profiles): 3000 chars, images (4), thread segments become comments on the first post
- mastodon (live): ~500 chars (varies by instance), images (4), threads, polls, CW
- threads (after Meta approval): 500 chars, images, carousels (10), threads
- In platform review, not available yet: instagram, facebook, tiktok, youtube, pinterest, reddit
- Not supported: discord, slack, telegram
## Full Documentation (markdown, agent-readable)
Fetch these .md files for complete details:
- API: https://octopost.ink/docs/api/overview.md
- Posts: https://octopost.ink/docs/api/posts.md
- Auth: https://octopost.ink/docs/api/authentication.md
- Errors: https://octopost.ink/docs/api/errors.md
- Platform guides: https://octopost.ink/docs/platforms/{platform}.mdUsing with Claude Code / Claude#
Adding Octopost docs as context#
You can tell Claude to read the Octopost documentation directly. Claude Code can fetch the raw markdown files and use them as reference.
Option 1: Reference in your CLAUDE.md
Add to your project's CLAUDE.md file:
## Octopost Integration
When working with Octopost, read the API docs:
- API overview: https://octopost.ink/docs/api/overview.md
- Posts endpoint: https://octopost.ink/docs/api/posts.md
- Platform guides: https://octopost.ink/docs/platforms/{platform}.mdOption 2: Ask Claude directly
Tell Claude to fetch the docs in conversation:
Read the Octopost API docs at https://octopost.ink/docs/api/overview.md
and https://octopost.ink/docs/api/posts.md, then help me write a script
that publishes a post to Twitter and Bluesky.Option 3: Download docs locally
For offline use or faster access, download the docs into your project:
mkdir -p docs/octopost
curl -o docs/octopost/api.md https://octopost.ink/docs/api/overview.md
curl -o docs/octopost/posts.md https://octopost.ink/docs/api/posts.mdThen reference them in your CLAUDE.md:
Octopost API docs are in docs/octopost/Example: Publishing with Claude Code#
Using my Octopost API key from $OCTOPOST_API_KEY, write a TypeScript script that:
1. Publishes "Just shipped a new feature!" to X
2. Logs the post URL from the responseClaude will use the Octopost API to generate working code:
const response = await fetch("https://octopost.ink/api/posts", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.OCTOPOST_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "Just shipped a new feature!",
platforms: ["twitter"],
published: true, // publish now instead of saving a draft
}),
});
const data = await response.json(); // 201 = live everywhere, 207 = partial or failed
for (const r of Object.values(data.results ?? {}) as any[]) {
console.log(`${r.platform}: ${r.status === "published" ? r.url : `${r.error} (${r.errorCode ?? "no code"})`}`);
}Add an Idempotency-Key header (a UUID) so an agent that retries after a timeout can't post twice. To save a draft first and publish it later, leave out published, then call POST /api/posts/{data.post.id}/publish; it returns the same status and results.
Using with Other Agents#
Any agent or automation tool that can make HTTP requests can use the Octopost API. The pattern is the same regardless of the agent framework:
- Set the base URL to
https://octopost.ink/api - Include the API key as a Bearer token in the
Authorizationheader - Send JSON with
Content-Type: application/json - Parse JSON responses for post IDs, URLs, and status information
Generic agent setup#
Give your agent these instructions:
To publish to social media, use the Octopost API:
- Base URL: https://octopost.ink/api
- Authentication: Authorization: Bearer {OCTOPOST_API_KEY}
- Content-Type: application/json
To create and publish a post:
1. POST /posts with {"content": "...", "platforms": ["twitter", "bluesky"]}
2. POST /posts/{id}/publish to publish immediately
The response includes per-platform results with post URLs.With tools/function calling#
If your agent supports function calling or tool use, define an Octopost tool:
{
"name": "publish_to_social_media",
"description": "Publish a post to one or more social media platforms via Octopost",
"parameters": {
"type": "object",
"properties": {
"content": {
"type": "string",
"description": "The post text content"
},
"platforms": {
"type": "array",
"items": {
"type": "string",
"enum": ["twitter", "bluesky", "mastodon", "linkedin", "threads"]
},
"description": "Which platforms to publish to"
},
"images": {
"type": "array",
"items": { "type": "string" },
"description": "Optional image URLs to attach"
}
},
"required": ["content", "platforms"]
}
}With MCP (Model Context Protocol)#
If your agent supports MCP, skip the wrapper: Octopost runs its own MCP server at https://octopost.ink/mcp (publish, schedule, queue, preview, thread splitting, file uploads, usage and more). See Connect an agent above and the MCP docs.
API Key Setup for Agents#
Generating an API key#
- Go to the API keys page
- Copy the account key at the top, or click Generate New Key and give it a descriptive name (e.g., "Claude Code agent", "GitHub Actions bot")
- Copy a generated key right away
API keys start with op_. Both the account key and generated keys work for the REST API and the MCP server. MCP clients that can sign in (claude.ai, Claude Desktop, ChatGPT, Claude Code, Cursor, Codex, VS Code) don't need a key at all.
Security considerations#
- Use separate keys for each agent or integration. If one key is compromised, you can revoke it without affecting others.
- Do not commit API keys to version control. Use environment variables or secret management systems.
- Store keys in environment variables:
export OCTOPOST_API_KEY="op_your_key_here" - In CI/CD pipelines, use your platform's secrets management (GitHub Actions secrets, Vercel environment variables, etc.).
- Rotate keys periodically. Delete old keys and generate new ones from the dashboard.
- Monitor usage. Check the dashboard for unexpected API activity. Each API key's usage is tracked separately.
- Revoke immediately if exposed. If a key appears in logs, commits, or public spaces, revoke it from the dashboard and generate a new one.
Permissions#
Keys you create on the API keys page have full access to the account's connected platforms and posts. You can set a daily post limit and default accounts per key. Octopost doesn't check per-endpoint scopes: a key stored with a scope list is rejected.