X/Twitter API is Now Pay-to-Play - Why I Disabled Cross-Posting

It's 2026 and I wanted a simple thing: when I publish a blog post, automatically cross-post it to X/Twitter alongside Bluesky. I had the code written, the credentials configured, tweepy installed. It should have been a 10-minute integration. Instead, it became an archaeology expedition through X's increasingly hostile developer ecosystem.

The Setup

The implementation was straightforward. I already had automated Bluesky cross-posting working via the AT Protocol. For Twitter, I used tweepy (v4.16.0, the latest) with OAuth 1.0a credentials from my existing developer app (App ID 15831, which I've had for years).

client = tweepy.Client(
    consumer_key=api_key,
    consumer_secret=api_secret,
    access_token=access_token,
    access_token_secret=access_token_secret,
)
response = client.create_tweet(text=tweet_text)

Simple. Clean. Should just work.

Error 1: 503 Service Unavailable

The first deploy to production returned 503 Service Unavailable. Not a great start, but transient errors happen. I assumed Twitter was having a bad day and moved on to debugging locally.

Error 2: 403 Forbidden — "App Not Attached to a Project"

Local testing revealed the real problem:

403 Forbidden
When authenticating requests to the Twitter API v2 endpoints,
you must use keys and tokens from a Twitter developer App
that is attached to a Project.

My app predates Twitter's "Project" requirement. When they restructured the developer portal under Elon's ownership, they added a requirement that all apps must be inside a "Project" to access v2 endpoints. My legacy standalone app wasn't.

The fix should have been simple: Go to the Developer Portal, create a Project, attach the app. But there was no "Create Project" button.

This isn't just me — it's a widely reported bug on the X Developer Community forums. Developers across all tiers — Free, Basic, Pro, and even the new Pay-Per-Use tier — report that the Projects section is missing entirely from the console. Some accounts have "ghost project" states where apps are internally associated with invisible/deleted projects that can't be managed.

The Fix: "Move to Package"

After digging through the portal, I found an obscure "Move to package" option buried in the app settings. This finally attached the app to a project. Authentication started working:

>>> client.get_me()
nerdymark

Victory? Not quite.

Error 3: 402 Payment Required

With auth working, I tried posting an actual tweet:

402 Payment Required
Your enrolled account [1146115155501039616] does not
have any credits to fulfill this request.

Credits. X now requires you to purchase credits to use the tweet endpoint. The "Free" tier is write-only with a credit system. Even posting a single tweet costs credits. The Basic tier is $200/month (doubled from previous pricing). There's a new Pay-Per-Use tier where you buy credits upfront and get charged per API call.

To be clear: the API that was free for over a decade, that enabled an entire ecosystem of bots, tools, and integrations — now has a literal paywall on the most basic operation (posting a tweet).

The Contrast: Bluesky

Meanwhile, my Bluesky cross-posting has been running flawlessly since I implemented it. The AT Protocol is open, well-documented, and free to use. No projects, no tiers, no credits. You authenticate with your handle and an app password, and you're done.

# Bluesky: just works
from atproto import Client
client = Client()
client.login(handle, password)
client.send_post(text="Hello from my blog!")

No 403s. No ghost projects. No credit system. Just an API that does what APIs are supposed to do.

What I Disabled

I've commented out the Twitter cross-posting code in both the immediate post-creation flow and the background scheduler. The tweepy dependency stays in requirements.txt in case X ever becomes developer-friendly again (not holding my breath). The credentials remain configured on our AWS environment.

If X introduces a reasonable free tier for posting — even 50 tweets/month would be fine for a personal blog — I'll re-enable it. Until then, my posts go to Bluesky automatically and X gets nothing.

Timeline of X API Hostility

For context, this is my fourth blog post about Twitter/X breaking things for developers:

  1. 2023: Twitter API Restrictions Kill Developer Projects — API pricing introduced
  2. 2023: Twitter Art Bot Suspended — my art bot killed
  3. 2024: API v1 Access Killed — legacy endpoints shut down
  4. 2026: This post — even v2 posting now requires payment

Each time, the platform gets worse for developers. Each time, the alternatives get better. Bluesky isn't just an alternative anymore — for developers, it's the default.