Post to X from a Python, Node or shell script
Send a POST request to https://octopost.ink/api/posts with your Octopost API key and the text. The post goes out on the X account you connected in the dashboard. No X developer app, no OAuth flow in your code and no token refresh: the key is the only credential your script holds.
What the X API asks of a small script
To post with the X API directly, you register a developer app, run an OAuth 2.0 PKCE flow in a browser to get a user token, store the refresh token, and refresh the access token every two hours. Images need a separate upload call first. For a cron job that posts a daily stat, that is more code than the job itself.
With Octopost the OAuth part happens once, in the dashboard, when you connect X. Your script sends JSON with a bearer key, and Octopost handles tokens, media upload and threads.
Copy-paste examples
Create an API key in the dashboard, connect your X account, then use any of these:
cURL (cron, shell scripts, CI)
curl -X POST https://octopost.ink/api/posts \
-H "Authorization: Bearer $OCTOPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Nightly build passed: 1,204 tests in 3m 12s", "platforms": ["twitter"], "published": true}'Python (requests)
import os, requests
r = requests.post(
"https://octopost.ink/api/posts",
headers={"Authorization": f"Bearer {os.environ['OCTOPOST_API_KEY']}"},
json={
"content": "New episode is up: how we cut our build time in half",
"platforms": ["twitter"],
"scheduledFor": "2026-11-10T15:00:00Z",
},
timeout=30,
)
r.raise_for_status()
print(r.json()["post"]["id"])TypeScript (Bun or Node 18+)
const res = 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: "v2.3.0 is out with offline mode",
platforms: ["twitter"],
mediaUrls: ["https://example.com/screenshot.png"],
queueStatus: "pending", // wait for approval in the dashboard
}),
});
if (!res.ok) throw new Error(await res.text());published: true posts now, scheduledFor posts at a set time, queueStatus: "queued" drops it into your interval queue and "pending" holds it until you approve it. Add segments to post a thread (see posting a thread through the API). Every field is in the Posts API reference, and for release announcements from CI there is a ready GitHub Actions workflow.
Limits worth knowing
- 280 characters per post, links count as 23. Longer text needs segments (a thread).
- Up to 4 images or 1 video per post, given as public URLs.
- scheduledFor must be ISO 8601 with a timezone offset, for example 2026-11-10T15:00:00Z.
- X posts use units from your monthly allowance: 1 for a plain post, 13 for a post with a link. Basic includes 500 a month.
- X is the live network. Bluesky, LinkedIn and Mastodon are in testing, and Threads opens after Meta approves the Octopost app.
Questions
Can I post to Twitter from Python without a developer account?
Yes. Connect your X account to Octopost once in the dashboard, then post from Python with an Octopost API key. Octopost publishes through its own X app, so you never create an X developer app.
How do I keep the API key safe in a script?
Read it from an environment variable or your CI secret store, as in the examples. Keys can be revoked and replaced in the dashboard at any time.
How do I post an image to X from a script?
Put a public image URL in mediaUrls. Octopost downloads it and uploads it to X for you, up to 4 images per post.
Can the script post as a different X account?
Yes, if you have connected more than one. Pass accounts: {"twitter": "@handle"}, or set a default account on the API key when you create it.
Will I know if a post failed?
With published: true the response includes publishResults for each network. Business plans can also subscribe to post.published and post.failed webhooks.
Start for $1
Every plan includes the MCP server and the REST API. Basic is $29 a month for 3 accounts, Premium $79 for 10, Business $199 for unlimited. The first 7 days cost $1, then the plan renews monthly unless you cancel.
Try it 7 days for $1Related
- Post to X from Claude Code
- Post an X thread through the API
- What posting to X through the API costs
- Announce a GitHub release on social
- Social media scheduling API
- Approve your agent’s posts before they go out
- Free thread splitter and character counter
- Pricing
- Octopost compared with Postiz, Buffer and Typefully