What it actually costs to post to X through the API in 2026
Posting to X through its API costs roughly $0.015 per post in 2026, rising to about $0.20 if the post contains a link — around thirteen times more. There is no free tier: an account with no credit receives 402 Payment Required. The developer app is billed, not the person posting.

X replaced its tiered plans with pay-per-use in February 2026. There is no free tier. The first real publish attempt we made returned 402 Payment Required, which is an unusually clear error and easy to misread as a broken key.
The numbers
| Post | Approximate cost |
|---|---|
| Plain text | $0.015 |
| Contains a link | $0.20 |
The gap is the part worth planning around. A link makes a post cost about thirteen times as much, which changes what belongs in the post body and what belongs in a reply.
The first-comment trick is now a cost decision
Putting a link in the first reply rather than the post is a familiar reach tactic on LinkedIn. On X in 2026 it is also a price decision: a post plus a reply carrying the link is two ordinary posts, roughly $0.03, against about $0.20 for one post with the link inside it.
The app pays, not the user
This matters for anyone building a tool other people will use. X bills the developer app, so every post your users make is charged to you. A thousand users posting ten times a month is ten thousand posts on your card, and no per-user pricing model fixes that by itself.
The realistic options are to have each user register their own X app, to absorb the cost and cap it with per-plan quotas, or to combine the two: a shared allowance with the option to add your own keys for more.
A separate permission for images, unannounced
Uploading an image requires the media.write scope. A connection made before you added images to your product carries a token without it, and the upload endpoint answers a bare 403 that mentions no scope at all.
The fix is to have the user authorise again — which does not require disconnecting first, since re-authorising replaces the token in place. Worth translating that 403 into "reconnect X" rather than showing it raw, because nothing in the raw error points there.