Last updated: September 2026

Schedule a Claude routine to post to X, Bluesky and LinkedIn

Create a Claude Code routine with a weekly schedule. Its prompt writes the week's posts and sends them in one request to POST https://opentweet.io/api/v1/posts, each with a scheduled_date and platforms. OpenTweet then publishes every post on time, even if a later routine run fails. Allow opentweet.io in the routine's cloud environment first.

Most guides stop at "tell the routine to post to X". The part that breaks in practice is the sandbox: routines block unknown hosts by default, and your local MCP servers do not come along. This page covers both, plus a daily publish-now variant.

7-day free trial. Cancel anytime. $11.99/mo after.

Daily publish or weekly batch?

A routine is a saved prompt that Anthropic runs on a schedule in a cloud session. You can have it publish once a day, or run once a week and let OpenTweet's scheduler do the publishing.

Daily, publish_nowWeekly, scheduled_date per post
Routine runs7 a week, or 5 on the weekdays preset1 a week
If a run fails or is skippedThat day gets no postThe week is already queued in OpenTweet and publishes on time
Review before it goes outNone. publish_now sends it straight awayEvery post sits in your OpenTweet queue for days. Edit or delete any of them
Duplicate checkBuilt in: a single post that matches one you posted or scheduled returns 409Not applied to multi-post requests. The prompt reads your recent posts instead
RetriesIdempotency-Key per day stops a second post that dayIdempotency-Key per week stops a second batch that week
Best forNews or metrics that change dailyEvergreen and planned content, which is most of it

The weekly batch is the one to start with. It uses one routine run instead of seven, and the posts are already in OpenTweet before the first one is due.

1. Connect your accounts and get a key

Sign up, connect X, Bluesky and LinkedIn in Settings, and generate an API key in the API section. It starts with ot_. No X developer account or LinkedIn developer app is needed.

2. Let the cloud environment reach OpenTweet

Every routine runs in a cloud environment. The Default one uses Trusted network access, which only lets through a fixed list of package registries and development domains. opentweet.io is not on it, so a plain curl fails with 403 and x-deny-reason: host_not_allowed. Pick one of these.

Pro and Max: add the key as an API credential

Open the routine's environment settings (the cloud icon below the Instructions box, then the settings icon), find API credentials, and select Add credential. Keep the type Bearer, set Allowed websites to opentweet.io, leave the header as Authorization with prefix Bearer, and paste your ot_ key as the value.

Anthropic's proxy then adds the key to every request for opentweet.io after it leaves the session, and the host becomes reachable even on Trusted. Claude never sees the key, which is why the prompts on this page send no Authorization header.

Team and Enterprise: environment variable plus allowlist

API credentials are not available on Team or Enterprise yet. Add the key under Environment variables:

Environment variables
OPENTWEET_API_KEY=ot_your_key_here

Then set Network access to Custom, list the hosts one per line in Allowed domains, and tick Also include default list of common package managers if the routine installs anything:

Allowed domains
opentweet.io
mcp.opentweet.io

Add -H "Authorization: Bearer $OPENTWEET_API_KEY" to each curl in the prompt. Anthropic notes that anyone who uses the environment can read its variables, so use a dedicated environment and a key you can revoke. Shared organization environments are changed by an Owner in admin settings.

Changes apply from the next run

New variables and network settings reach sessions started after you save. A run already in progress keeps the old values.

3. Create the weekly routine

Go to claude.ai/code/routines and click New routine, or run /schedule in the Claude Code CLI (it needs a claude.ai subscription login). Add a small GitHub repository that holds voice.md (how you write) and topics.md (what to write about); the routine clones it on every run. Select the environment from step 2, choose the Weekly preset, and pick a time such as Sunday 18:00. Times are in your local zone.

Paste this as the prompt:

routine prompt: weekly batch
You are my social media manager. This routine runs once a week and plans
the next five weekdays of posts. OpenTweet publishes them; you only write
and schedule them.

1. Read voice.md and topics.md in this repository.

2. See what already went out or is queued, so you do not repeat yourself:
     curl -s "https://opentweet.io/api/v1/posts?status=posted&limit=50"
     curl -s "https://opentweet.io/api/v1/posts?status=scheduled&limit=50"
   Do not reuse a topic or an opening line from either list.

3. Write 10 posts: Monday to Friday of the coming week, at 09:00 and 16:00
   America/New_York. Each post under 280 characters. No links.

4. Send all 10 in ONE request. Convert each time to UTC ISO 8601.
     curl -s -w "\n%{http_code}" -X POST https://opentweet.io/api/v1/posts \
       -H "Content-Type: application/json" \
       -H "Idempotency-Key: week-<ISO year>-<ISO week number>" \
       -d '{"platforms": ["x", "bluesky", "linkedin"],
            "posts": [
              {"text": "...", "scheduled_date": "2026-09-28T13:00:00Z"},
              {"text": "...", "scheduled_date": "2026-09-28T20:00:00Z"}
            ]}'

5. If the status is not 201, print the status and the body and stop.
   Do not rewrite the posts and send them again.

6. Finish with a table: post id, scheduled time, first 60 characters.

Authentication: the environment attaches my OpenTweet key to requests for
opentweet.io, so do not add an Authorization header.

Why one request: POST /api/v1/posts accepts a posts array of up to 50, and a top-level platforms applies to each post that does not set its own. OpenTweet validates the whole batch before creating anything, so one invalid post means none are created.

Why the Idempotency-Key: OpenTweet stores a successful response against the key for 24 hours. If the same batch is sent again within that window, the second call replays the first response. If a second run writes different posts under the same key, it gets 422 idempotency_key_reused instead of a second week of posts. Failed requests are not stored, so a fixed retry still goes through.

Remove connectors you do not need. Every connector on your account is added to a new routine by default, and Claude can use all of their tools, including writes, without asking.

Click Run now once, open the run, and check for a 201 and ten ids. The posts should then show in your OpenTweet queue.

The daily publish-now variant

Use a Daily or Weekdays trigger when the post depends on that day's data. A single-post request runs OpenTweet's duplicate check: if the text matches something you already posted or scheduled, you get 409 with duplicate_content instead of a repeat.

routine prompt: daily
You post one update a day for me on X, Bluesky and LinkedIn.

1. Read voice.md and topics.md in this repository.
2. curl -s "https://opentweet.io/api/v1/posts?status=posted&limit=20"
   and do not repeat a topic or opening line from it.
3. Write one post under 280 characters. No links.
4. Publish it:
     curl -s -w "\n%{http_code}" -X POST https://opentweet.io/api/v1/posts \
       -H "Content-Type: application/json" \
       -H "Idempotency-Key: day-<YYYY-MM-DD>" \
       -d '{"text": "...", "platforms": ["x", "bluesky", "linkedin"], "publish_now": true}'
5. If the status is 409 with duplicate_content, write a clearly different
   post and try once more. On any other error, print it and stop.
6. Print posts[0].results so I can see the outcome on each network.

The response carries one entry per network in posts[0].results. A post over Bluesky's 300 characters is skipped on Bluesky with a reason while X and LinkedIn still publish.

Using the MCP server instead of curl

MCP servers you added with claude mcp add stay on your machine and do not reach routines. There are two ways to give a routine the OpenTweet tools.

A committed .mcp.json

A routine with exactly one repository loads that repository's .mcp.json, without the approval prompt you see locally. Claude Code expands ${VAR} in headers, so the key stays in the environment variable from step 2 and out of git:

.mcp.json
{
  "mcpServers": {
    "opentweet": {
      "type": "http",
      "url": "https://mcp.opentweet.io/mcp",
      "headers": { "Authorization": "Bearer ${OPENTWEET_API_KEY}" }
    }
  }
}

Anthropic's docs only exempt claude.ai connectors from the network allowlist, so keep mcp.opentweet.io in Allowed domains for this route. Then replace step 4 of the weekly prompt with:

prompt excerpt
For each post, call opentweet_create_tweet with:
  text, platforms: ["x", "bluesky", "linkedin"], scheduled_date (UTC ISO 8601)

Before writing, call opentweet_list_tweets to see what is already
scheduled and posted, and do not repeat it.

opentweet_batch_schedule also exists, but it schedules posts that already exist as drafts, so creating each post with its scheduled_date is one step shorter.

A claude.ai custom connector

Connectors travel through Anthropic's servers, so they need no allowlist entry, and they are what Cowork scheduled tasks use. The catch: OpenTweet's hosted server authenticates with Authorization: Bearer ot_... and has no OAuth, and Anthropic lists request-header auth for custom connectors as beta, entered by an organization administrator. If the Request headers section appears when you add a custom connector at claude.ai/customize/connectors, enter https://mcp.opentweet.io/mcp with the header value Bearer ot_your_key. If it does not, use one of the routes above.

Routine limits to know

From Anthropic's routines and cloud environment docs, as of September 2026.

Plans with routinesPro, Max, Team and Enterprise. Team and Enterprise Owners can switch routines off for everyone.
Where to create themclaude.ai/code/routines, the Desktop app (Routines, then Cloud), or /schedule in the Claude Code CLI
Shortest intervalOne hour. Presets are hourly, daily, weekdays and weekly; set custom cron with /schedule update
Runs per dayA daily cap per account on top of normal subscription usage. The docs do not publish the number; your remaining runs show at claude.ai/code/routines
One-off runsDo not count against the daily routine cap
Default networkTrusted: a fixed allowlist of package registries and dev domains. opentweet.io is not on it
SecretsAPI credentials (key hidden from Claude) on Pro and Max only. Team and Enterprise use environment variables, which anyone using the environment can read
StatusResearch preview. Behavior, limits and the API surface may change

Claude Cowork has its own scheduled tasks, on all paid plans. Type /schedule in a Cowork task or open Scheduled in the sidebar; cadences are hourly, daily, weekly, weekdays or manual. They use your connected tools, so they reach OpenTweet only through the custom connector above.

Guardrails before you leave it running

Always pass platforms

A post with no platforms value follows the account auto cross-post setting, which can mean every connected network. An explicit array is honoured exactly.

One bad post fails the whole batch

If x is a target and any post is over your X character limit, the request returns 400 validation_failed and nothing is created. Ask for under 280 characters unless you have X Premium.

The batch counts against today

Scheduling checks how many posts your plan can still publish today: 20 on Pro, 100 on Advanced, 300 on Agency. Keep a weekly batch under that, at most 50 posts per request, and under 300 queued posts in total.

Links cost allowance

Pro includes no link posts per day; Advanced includes 10 and Agency 20. Over the allowance OpenTweet strips the URL from the text. Tell the routine "no links" unless your plan covers them.

Want a human check?

Leave out scheduled_date and the posts are saved as drafts. They wait in the OpenTweet dashboard until you schedule or delete them.

Read the transcript, not the green dot

Anthropic notes that a green run status only means the session exited cleanly. Blocked requests and API errors show up inside the run, which is why the prompt prints the status code.

LinkedIn specifics

LinkedIn posts go to your personal profile only. The LinkedIn sign-in lasts 60 days with no refresh, so OpenTweet emails you to reconnect and holds scheduled LinkedIn posts until you do. Hashtags and @mentions publish as plain text there.

Frequently asked questions

Can a Claude routine post to X every day automatically?

Yes. Create a routine with a daily schedule trigger whose prompt writes a post and sends it to OpenTweet's POST /api/v1/posts with publish_now set to true. The routine runs in Anthropic's cloud, so your laptop can be closed. A more reliable setup is one weekly routine that schedules the whole week in OpenTweet, so a missed run does not mean a missed post.

Why does my routine get a 403 host_not_allowed when it calls opentweet.io?

The Default cloud environment uses Trusted network access, which only allows a fixed list of package registries and development domains. Either add your OpenTweet key as an API credential for opentweet.io (Pro and Max), which also makes the host reachable, or switch the environment's network access to Custom and add opentweet.io and mcp.opentweet.io to Allowed domains.

Will my routine see the MCP servers I added with claude mcp add?

No. Those live in ~/.claude.json on your machine. A routine gets the connectors on your claude.ai account, plus servers declared in a committed .mcp.json when the routine has exactly one repository.

How often can a routine run?

At most once an hour. Anthropic rejects cron expressions that run more often. There is also a daily cap on routine runs per account, which the docs do not state as a number; claude.ai/code/routines shows how many you have left.

Can Claude post to LinkedIn and Bluesky from a routine too?

Yes. Put "linkedin" and "bluesky" in the platforms array next to "x". LinkedIn posts go to your personal profile; Company Pages are not supported. Each network reports its own result, so a post over Bluesky's 300 characters is skipped there while X and LinkedIn still publish.

Does this work with Claude Cowork scheduled tasks?

The same prompt works. Cowork scheduled tasks are created with /schedule in a Cowork task or from Scheduled in the sidebar, run hourly, daily, weekly or on weekdays, and use your connected tools. Cowork reaches OpenTweet through a connector, so it depends on adding the hosted MCP server as a custom connector with an Authorization request header, which Anthropic lists as beta.

Can I approve posts before they publish?

Yes. Drop scheduled_date from each post and OpenTweet saves them as drafts. You then schedule, edit or delete them in the dashboard. The weekly batch also gives you days to change anything that is already scheduled.

One routine a week, posts every day

Claude writes the week. OpenTweet publishes it to X, Bluesky and LinkedIn on schedule.

7-day free trial. Cancel anytime.