taupe Building, using, and running it.

Article

Human approval did not make my X automation compliant

Human approval did not make my X automation compliant

I used to auto-post blog articles to X with Google Apps Script and the X API. In May 2026 I noticed it had silently stopped: the script reported success, while the API request had failed with CreditsDepleted.

So I dropped API posting and moved to an approval-based setup — Codex reads the article, drafts the post, I approve it, and it goes out through an already-logged-in Chrome session. A human decides what ships. That felt like the responsible version.

Originally published in Japanese on May 22, 2026. This English version was written in September 2026 and corrects several points from the original.

It was not. Re-reading X’s Developer Guidelines afterwards, I had collapsed two independent questions into one. Whether a human approves the content and how the content reaches X are separate rules, and satisfying the first does nothing for the second. The Guidelines are explicit that non-API automation, including browser automation, is prohibited, and that violations can cost you the app, your API access, or the account itself.

This is not a guide to avoiding X API charges. It is a record of taking a setup I had already built and re-examining it against the actual policy text — and finding that several things I believed were out of date.

What CreditsDepleted actually meant

At the time I read the failure as a quota problem. It was a billing model change.

X launched pay-per-use API pricing on February 6, 2026. There is no subscription in that model — you hold a credit balance and each read and write draws it down. CreditsDepleted accompanies an HTTP 402 Payment Required and means the enrolled account has no credits to fulfill the request. X’s pricing documentation notes that a balance can go slightly negative, and that requests are blocked until you top it back up.

Worth flagging for anyone debugging the same thing: CreditsDepleted is undocumented. X’s response-codes reference lists 200, 201, 204, 400, 401, 403, 404, 409, 429, 500, 502, 503 and 504. There is no 402 entry and no mention of the name. What you actually get is HTTP 402 with a problem type of https://api.x.com/2/problems/credits-depleted, and that URL redirects to X’s own response-codes reference — the very page that omits 402. I have found no official statement of what the name means; I am inferring it from the HTTP status and my own depleted balance. X’s developer forum has one thread posting the payload and the documentation gap, and another where the same error fired while the reporter still showed a $10 balance — neither has a reply, and the second one argues against the obvious reading. Treat the meaning as unconfirmed. That is a weaker citation than I would like, and I would rather say so than pretend otherwise.

And the number that reframes the whole economics of a blog auto-poster: under pay-per-use, creating a post costs $0.015 — but a post containing a URL costs $0.200. Every “new article is up” post contains a URL. That is the actual unit price of the thing I was building, and I did not know it when I decided the API was not worth it.

Human approval and access method are different axes

The setup I moved to was genuinely good at one thing. Codex would pick a candidate from WordPress, read the body, and draft something for X. I checked the content and the destination account before anything went out. That is a real control on what gets published: no claims absent from the article, no wrong account, no overstatement, and a stop button before send.

X’s Developer Guidelines check something else in addition to whether an action is user-initiated: whether you are using the official API. The Guidelines phrase it as a question: are you only using the official API, not scraping or browser automation? They also list non-API automation in their prohibited-practices table. The page states that violations “can result in app suspension, API access revocation, or permanent account bans” — it does not promise a specific penalty, which is not a reason to treat it as survivable. Their prohibited-practices table names it directly: browser scripting, scraping, any automation outside the official API.

So: approval controls what you send. Official-API-only controls how you send it. Bundling them together as “safety measures” was my mistake. A script or agent driving a logged-in browser to post has to be read as falling under the prohibition on non-API browser automation, regardless of who approved the text.

One correction on sourcing, since I got it wrong originally: this language lives in the Developer Guidelines, not the Developer Policy. The Policy document does not contain it. If you cite this, cite the Guidelines.

There is a third rule I had not noticed at all, and it is the one most likely to catch anyone building what I was building. The Guidelines put AI-generated content and replies in a “gray areas” section and require prior approval from X before deployment, obtained through X’s policy support form — stating explicitly that deploying AI-generated replies without approval is a violation even when the content itself is helpful. Automated accounts also carry disclosure obligations: the Automated label on the profile, a bio identifying the bot and its operator, and a link to a human-managed account.

None of this is a legal assessment, and it is not a prediction about what enforcement any particular account would see. It is reading the published platform rules and concluding that my setup did not survive them.

Auto-liking is a separate question, and it is now moot

The Guidelines are unambiguous here: likes must be directly initiated by the authenticated user. Automated, bulk, or indiscriminate liking — including auto-liking by keyword, hashtag, user, or schedule — is prohibited, apps may not offer auto-like features, and this applies to bots, mobile apps, browser extensions, and any integration.

Note what that rules out: switching an auto-like feature on once is not the same as directly initiating each like. So a post-approval workflow and an auto-like feature are not the same category of thing, even though both involve a human clicking something once.

And “just use the official API for it” is no longer an option anyway. Per X’s changelog, following, likes, and quote-posts via the API were removed from all self-serve tiers, announced on April 16, 2026. Quote-posting now requires an Enterprise plan, per the Create Post reference; the changelog entry does not say where following and likes went. That came after the free tier had already lost POST /2/users/:id/likes and POST /2/users/:id/following in August 2025. The technical route is closed independently of whether the behavior would have been permitted.

The general lesson: do not lump posting, scheduling, liking, replying, and following into one bucket called “X automation.” Each has its own rule about the required access method and its own rule about who must initiate the action.

Codex is still useful right up to the send button

Removing browser automation does not remove the AI from the workflow. Everything below happens without sending a single operation to X:

  • Select candidates from published articles
  • Re-read the article body
  • Track what has already been promoted
  • Draft the post text
  • Check length
  • Remove claims not supported by the article, and soften overstated ones
  • Name the intended destination account explicitly

This is where the value was in the first place. Pressing the post button was never the hard part. The improvement over my old scheduled-spreadsheet approach was that each post came from actually re-reading the article that day, rather than replaying a line written weeks earlier. With Codex handling selection and drafting and me posting through X’s native UI, that survives intact.

One extra manual step. The part that used to cost real thought — composing something specific from scratch every time — stays automated.

Two viable routes, and their real costs

Route one: stop the AI before the send. Codex does selection, reading, and drafting. I post or schedule from X’s native UI as the authenticated user. Simple, and I see the text and the account with my own eyes before it goes.

Route two: decide what genuinely needs automating and use the official API for that. Design against the current access model, cost, and rate limits.

On cost, be concrete before committing. Every X API price below was checked on September 7, 2026, and X changed its pricing repeatedly through 2026 — verify in the Developer Console before planning against them. Under pay-per-use, a link-bearing post is $0.200 — so one announcement a day is roughly $6 a month, three a day roughly $18. Reads are separately metered (a post read is $0.005, a user read $0.010), and pay-per-usage plans are capped at three million post reads per monthly billing cycle.

Do not price this against a tier name, because the tiers are gone. X’s pricing page now opens with “The X API uses pay-per-usage pricing with no subscriptions.” The legacy Basic plan was moved to pay-per-use from June 2026 and the legacy Pro plan from September 2026, both announced on X’s developer forum. As of September 2026 the choice is pay-per-use or Enterprise. Any article you find quoting a monthly Free, Basic, or Pro allowance — including older versions of this one — is describing a model that no longer exists.

Choosing the official API also does not dissolve the other restrictions. Spam, unsolicited interaction, and auto-liking rules apply regardless of access method.

Both routes cost something. Route one costs your time. Route two costs implementation, money, rate-limit handling, and operational record-keeping. I have not settled on which becomes my standard, and I am not going to pretend otherwise for the sake of a tidy ending. What I have decided is not to leave non-API browser automation documented as a recommended procedure.

Draw the AI’s boundary before the external action

What generalizes past X:

  • The human sets direction
  • The AI gathers candidates
  • The AI reads and drafts
  • The human checks content and destination
  • Operations against an external service go through that service’s official mechanism, under its current policy

Approval points matter. But an approval point does not license the technical means. When you hand an AI agent the ability to act on an external service, check three things separately: is the content correct, does the agent have authority to act, and does the service permit this technical method.

The more convenient the setup, the more it needs re-reading

A depleted credit balance pushed me from the X API to Codex plus a logged-in Chrome session with human approval. As a mechanism for controlling what gets published, it worked well.

Going back to the Developer Guidelines afterwards, human approval and non-API browser automation turned out to be different questions, and auto-liking has a further requirement that each like be directly initiated by the authenticated user — a route that has since been removed from self-serve tiers entirely. My original write-up also misattributed the source and misread a billing change as a quota.

So this stays on the site as a revision record rather than a recommended procedure. Codex remains genuinely useful for selection, reading, and drafting. Whether posting happens through the native UI or through the official API is still open. What is settled is the habit: separate what you are approving from the mechanism you are using to act, and go back and re-read the rules for the parts of your setup that work well enough that you stopped thinking about them.

References

Next

These notes come from running this setup daily.

About the author

Hidekazu Ishikawa

Hidekazu Ishikawa builds and runs web products with AI agents from Japan. Available for consulting on AI workflow design and web development.

Next

Keep reading.