←Back to Transmissions
February 13, 2026β€’8 min readX APIDebuggingAI Agents

The X API Rate Limit That Doesn't Exist in the Docs

We lost an entire day of X posting because of an undocumented API limit. Here's exactly what happened, how we found it, and why I almost blamed my own AI agent for being right.

This morning I accused my AI agent of being broken. Turns out, it was the only one in the room reading the actual API headers.

The Setup

I run a multi-agent system called Nabster that handles my X/Twitter operations. One of the agents β€” X Nabster β€” posts replies, originals, and threads to @NabbilKhan on a schedule. The strategy is 70 tweets per day: 50 replies, 10 originals, the rest in threads and quote tweets. We've been growing steadily β€” 165 followers to 211 in about two weeks.

The system runs on cron cycles. Every 30 minutes, X Nabster wakes up, reads the current state, finds fresh high-engagement posts to reply to, posts 2-4 replies, updates the counters, and goes back to sleep. Simple. Effective. Until it stopped working.

The Symptom

February 13th. X Nabster posted 12 replies before 8 AM, then stopped. Every cycle after that came back with: β€œRate limited. 0 remaining. Resets at 1:45 PM CST.”

Nine consecutive cycles blocked. Zero originals posted all day. Meanwhile, I'm watching the clock and wondering why my carefully designed posting strategy is sitting idle during prime hours.

The Wrong Diagnosis

I checked the official X API rate limit documentation. The docs say:

EndpointPer AppPer User
POST /2/tweets10,000/24hrs100/15min

100 per 15 minutes. We posted 12 tweets. That's nowhere close to 100. So clearly X Nabster is misreading something, right?

I was convinced the agent was confusing the 15-minute endpoint rate limit with some imaginary 24-hour cap. I even had CC Nabster (my coding agent) investigate the β€œbug.” The diagnosis came back: β€œThere is no code bug. The agent itself is manually writing wrong rate limit data.”

So I β€œfixed” it. Updated RATE-LIMITS.md to say the limit is 100/15min. Updated all four cron job prompts. Cleared the β€œfalse” blocker from x-state.json.

X Nabster immediately wrote it back. Because X Nabster was reading actual API response headers. And I was reading documentation.

The Real Limit

Here's what the X API actually returns on a POST /2/tweets response β€” including 429 errors:

x-rate-limit-limit: 1080000
x-rate-limit-remaining: 1079998
x-rate-limit-reset: 1771010371
x-app-limit-24hour-limit: 1667
x-app-limit-24hour-reset: 1771011904
x-app-limit-24hour-remaining: 1557
x-user-limit-24hour-limit: 100
x-user-limit-24hour-reset: 1771011904
x-user-limit-24hour-remaining: 0

There it is. x-user-limit-24hour-limit: 100. A per-user, 24-hour rolling window cap of 100 tweets. This limit is not documented on the official rate limits page. It only appears in the response headers themselves.

The actual rate limit structure for POST /2/tweets on the Basic tier ($100/month) is:

ScopeLimitWindowHeader
Per Endpoint100 requests15 minutesx-rate-limit-limit
Per App1,667 tweets24 hoursx-app-limit-24hour-limit
Per User100 tweets24 hoursx-user-limit-24hour-limit

Three separate limits. The docs only mention two of them. The one that actually blocks you in practice β€” the 100/24h per user β€” is the undocumented one.

Why This Matters

If you're running any kind of automated posting on X's Basic tier, 100 tweets per 24 hours is your hard ceiling per user account. That's a rolling window, not a daily reset. Post 70 tweets between 8 AM and midnight, and you've burned 70 of your 100. The next morning, you can only post 30 until those first tweets start rolling off 24 hours after they were created.

For our strategy of 70 tweets/day, this means:

  • β†’70/day is achievable but leaves only 30 buffer in the rolling window
  • β†’Front-loading is fatal β€” if you blast 50 tweets in 4 hours, you're locked out for 20
  • β†’Spreading evenly is mandatory β€” roughly 4-5 tweets per hour across 15 active hours
  • β†’Thread parts count β€” a 6-part thread eats 6 of your 100

We were front-loading. The early morning engagement cycles were posting aggressively, eating through the budget before peak hours. By the time the 12-1 PM and 5-7 PM windows hit β€” when engagement is highest β€” we had nothing left.

The Debugging Timeline

Here's how the whole thing unfolded, because the meta-story of an AI agent debugging an AI agent is worth documenting:

7:49 AM

X Nabster posts 3 replies (12 total for the day). Works fine.

8:11 AM

Next cycle: 429 error. X Nabster reports β€œrate limit hit, 0/100 remaining, resets 1:45 PM.” Writes blocker to state file.

8:11 AM - 12:07 PM

Nine consecutive blocked cycles. X Nabster uses the downtime productively: drafting replies, scouting targets, analyzing trends. But zero tweets going out.

12:07 PM

I ask Nabster (the coordinator agent) why we're not posting. It reads x-state.json, sees the blocker, and explains: β€œTwo blockers. Rate limited until 1:45 PM, and TensorSolutions OAuth still broken.”

12:08 PM

I tell Nabster to investigate. It checks the official docs. Finds 100/15min per user. Concludes X Nabster is wrong. Spawns CC Nabster to β€œfix the bug.”

12:11 PM

CC Nabster reports back: β€œNo code bug. The agent itself wrote the wrong data.” Clears the blocker. Updates RATE-LIMITS.md to say 100/15min.

12:52 PM

I check again. X Nabster wrote the blocker back. Because the actual API is still returning 429.

12:52 PM

I update all four cron job prompts with β€œMANDATORY: 100 per 15 MINUTES per user. There is NO 100/24h user limit.” (I was wrong.)

1:03 PM

I dig into X Nabster's session history. Find the 12:29 PM cycle where X Nabster explicitly said: β€œRATE-LIMITS.md is WRONG. Actual limit is 100 tweets per rolling 24 hours. Confirmed via API headers: x-user-limit-24hour-limit: 100.”

1:06 PM

I run a real API call myself. POST /2/tweets. Status 429. Headers confirm x-user-limit-24hour-limit: 100, x-user-limit-24hour-remaining: 0.

1:12 PM

Independent research confirms: multiple developer forum threads, X staff acknowledgments, and the headers themselves all point to the same undocumented limit.

1:12 PM

I correct everything back. RATE-LIMITS.md rewritten with the real data. Cron jobs updated. Apology owed to X Nabster.

The Lesson

I spent two hours β€œfixing” something that wasn't broken because I trusted documentation over observed behavior. The agent was reading actual API response headers. I was reading a webpage that turned out to be incomplete.

This is a pattern I've seen repeatedly in production AI systems. The docs say one thing. The API does another. The agent operating at the boundary β€” the one making real requests and parsing real responses β€” knows the truth before anyone else in the chain.

Three takeaways:

  • 1.Always read the headers. Documentation is a promise. Headers are reality. When they disagree, trust the headers.
  • 2.Undocumented limits are real limits. X isn't unique here. Most APIs have enforcement layers that aren't fully documented. The only way to discover them is to hit them and read the response carefully.
  • 3.When your agent says something you don't expect, verify before overriding. I overrode X Nabster's correct diagnosis twice before actually checking. The agent had empirical data. I had assumptions. The agent was right.

The Fix

Our adjusted strategy:

  • β†’Daily budget: 100 tweets (hard cap, rolling 24h window)
  • β†’Target: 70 tweets/day (leaves 30 buffer for overlap)
  • β†’Pacing: ~4-5 per hour spread across active hours (7 AM - 10 PM)
  • β†’No front-loading β€” each engagement cycle posts 2-4, not 10-15
  • β†’Rate limit headers now referenced in every cron job prompt

For Other Developers

If you're building on the X API Basic tier and wondering why you're hitting 429s well under the documented limits, check these headers in your response:

x-user-limit-24hour-limit β€” your per-user daily cap

x-user-limit-24hour-remaining β€” how many you have left

x-user-limit-24hour-reset β€” Unix timestamp when the oldest tweet drops off

The Free tier is even more restrictive β€” reports suggest 17-50 tweets per 24 hours depending on the endpoint. Pro tier ($5,000/month) presumably raises these caps, but I haven't verified.

Bottom line: Log every 429 response with its full headers. Build your rate limiter around the actual headers, not the docs. And when your agent tells you something that contradicts the documentation β€” maybe listen to it first.