Last updated: August 31, 2026
X Activity API webhooks: events, scopes, and costs
The X Activity API sends webhook events to your server when things happen on your account. On June 4, 2026, X added post.create and post.delete. On July 21, 2026, it added mute and block events, which need OAuth 2.0 with the mute.read and block.read scopes. Delivered events bill per event. post.delete and dm.sent are free.
The event list is in the docs. The billing is not, at least not in one place, which is how people end up subscribing an account to everything and finding out what it costs at the end of the cycle. Here is the whole table.
The event and cost table
Current as of August 2026 on self-serve pay-per-use access. X notes prices are subject to change, so treat the Developer Console as the source of truth for your account.
| Event | Added | Auth | Billing | What it is good for |
|---|---|---|---|---|
| post.create | June 4, 2026 | OAuth 1.0a or OAuth 2.0 | $0.001 to $0.010per delivered event | Fires when the subscribed account publishes a post. The clean trigger for cross-posting, archiving, and "did my scheduler actually fire" checks. |
| post.delete | June 4, 2026 | OAuth 1.0a or OAuth 2.0 | Freenot billed | Fires when a post disappears. Costs nothing, so there is no reason not to subscribe. Best available signal that a post was removed, whether by you or not. |
| mute | July 21, 2026 | OAuth 2.0, scope mute.read | $0.001 to $0.010per delivered event | Fires on mute and unmute activity. Useful as a negative-signal feed. Mute carries a -58.8 weight in the Phoenix ranker, so it is worth knowing when it happens. |
| block | July 21, 2026 | OAuth 2.0, scope block.read | $0.001 to $0.010per delivered event | Fires on block and unblock activity. Same idea as mute, harder signal. Block sits at -31.2 in the published Phoenix weights. |
| dm.sent | Pre-2026 | OAuth 1.0a or OAuth 2.0 | Freenot billed | Fires when the account sends a DM. Free, which makes it the cheapest way to keep an outbound DM log in sync with your own database. |
Read the band correctly
Billable activity events are priced in a $0.001 to $0.010 per-event band rather than at one flat rate, in the same order of magnitude as pay-per-use reads ($0.005 per post returned, $0.010 per user returned). We are not going to guess where inside the band each event lands. Confirm the exact per-event rate in the Developer Console before you subscribe a high-traffic account, because the difference between the two ends of that band is 10x.Why webhooks got interesting in 2026
Under the old subscription tiers, polling was free at the margin. You paid $200 a month and made as many calls as your rate limit allowed. Under pay-per-use, every poll costs money whether or not it returns anything.
Do the arithmetic on a one-minute mention poller. That is 43,200 requests a month. Most of them return nothing, and the ones that do return posts bill at $0.005 each. A webhook charges you only when something actually happened, capped at $0.010 for the most expensive event type. For anything below a few hundred events a day, push beats pull by an order of magnitude.
The 2026 additions matter because they close the gaps that forced people back to polling. post.create means you no longer need to poll your own timeline to know a post went out. post.delete, which is free, means you no longer need to re-read your posts to discover one vanished. mute and block turn a previously invisible negative signal into a feed.
# 1. Register the webhook URL for your dev environment
curl -X POST "https://api.x.com/2/webhooks" \
-H "Authorization: Bearer $X_APP_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "url": "https://your-app.example.com/x/events" }'
# 2. Subscribe the authorizing user's account to it.
# mute and block require OAuth 2.0 with mute.read / block.read.
curl -X POST "https://api.x.com/2/webhooks/$WEBHOOK_ID/subscriptions" \
-H "Authorization: Bearer $X_USER_ACCESS_TOKEN"Two things to get right up front. First, mute and block need OAuth 2.0 with mute.read and block.read. If your app is still on OAuth 1.0a for the older Activity API events, you need a second authorization path. Second, your handler must return 2xx quickly. X retries failed deliveries, and a retried delivery of a billable event is a delivery you can be charged for.
// Your handler. Every delivery you accept is a billable event,
// except post.delete and dm.sent, which are free.
export async function POST(req: Request) {
const body = await req.json();
if (body.post_delete_events) {
// Free event. Log it, alert on it, reconcile your own records.
await markPostMissing(body.post_delete_events[0].id);
}
if (body.post_create_events) {
// Billable. Only subscribe if you will act on it.
await archivePost(body.post_create_events[0]);
}
return new Response(null, { status: 200 });
}What webhooks do not give you
The Activity API is entirely inbound. It reports what already happened. It does not post, it does not schedule, and it does not react on its own. Every automation people actually want is a pair: an event in, and a post out.
The out half is the part that got harder in 2026. Replies through POST /2/tweets now require the original author to have summoned you first. Likes, follows, and quote-post writes moved to Enterprise in April 2026. So the reflex design, watch for an event and engage automatically, is no longer buildable on self-serve access even with perfect webhook plumbing.
Do not wire a webhook straight into an engagement action
Event-triggered liking and replying is the pattern X removed 42,000 accounts for in April 2026. See what happens after a purge suspension if you already built one.The other direction: connectors
An X webhook tells you what happened on X. Most of the automations people build are the mirror image: something happened in your systems, and it should become a post. That is what OpenTweet connectors do, and they need no X developer account, no webhook registration, and no per-event billing.
- GitHub connector: a release, a merged PR, or a commit becomes a drafted post.
- Stripe connector: revenue milestones and metric moves become build-in-public posts.
- RSS connector: a new item in any feed becomes a scheduled post, with no $0.20 link surcharge.
- A generic API connector for anything you can POST to, if you would rather push events yourself.
And if you would rather do the plumbing yourself, one REST call from your own webhook handler is enough:
# Outbound, the other direction: a connector turns an event in
# your own systems into a scheduled post, with no X developer account.
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer ot_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"text": "New release is live. Changelog in the replies.",
"scheduled_date": "2026-09-02T15:00:00Z"
}'7-day free trial. Cancel anytime.
Frequently asked questions
What is the X Activity API?
It is the push side of the X API. Instead of polling an endpoint on a timer, you register an HTTPS webhook URL and subscribe an account to it. X then delivers a JSON payload to your server every time a subscribed event happens on that account. It removes the polling loop, which on pay-per-use was the single most expensive thing most integrations did.
What events did X add to the Activity API in 2026?
On June 4, 2026 X added post.create and post.delete. On July 21, 2026 it added mute and block events, which require OAuth 2.0 with the mute.read and block.read scopes. Direct message events were already available.
What do X Activity API webhook events cost?
Delivered events bill per event in a band from $0.001 to $0.010 each. Two events are free and always have been: post.delete and dm.sent. The Developer Console shows your current per-event rate and is the source of truth, since X notes prices are subject to change.
Which events are free on the X Activity API?
post.delete and dm.sent. Neither is billed. That makes post.delete the cheapest possible way to detect that one of your posts disappeared, which is a genuinely useful moderation and compliance signal.
What OAuth scopes do the mute and block events need?
The mute and block events launched July 21, 2026 require OAuth 2.0 with the mute.read and block.read scopes on the user token. OAuth 1.0a will not carry them. If your app is still on 1.0a for the older Activity API events, you need a second authorization path to receive mute and block.
Is a webhook cheaper than polling the X API?
Almost always. A poller that checks mentions every minute makes 43,200 read calls a month before it returns anything useful, and reads bill per post returned at $0.005. A webhook bills only when something actually happened, in a band topping out at $0.010. The saving scales with how empty your polls were.
Do I need webhooks to schedule posts on X?
No. Scheduling is not an X API feature at all. The X API posts immediately or not at all, and the Activity API only tells you what already happened. If you want scheduled publishing, you need your own scheduler or a platform that runs one, such as OpenTweet.
Related guides
Events in, posts out. The rest of the 2026 X API picture.
OpenTweet connectors
Turn events in your own systems into scheduled X posts. No developer account.
GitHub to X
Releases, PRs, and commits become drafted posts you approve.
X API pay-per-use explained
Every rate, how credits work, and what real workloads cost.
The reply restriction
Why event-triggered replies stopped working in February 2026.
X API cost calculator
Compare a polling workload against an event-driven one.
Developer API and keys
REST endpoints, one bearer key, and usage tracking.
Events in, posts out
Connect GitHub, Stripe, RSS, or your own API and let each event become a scheduled post. Flat monthly fee, no per-event billing, no X developer account.
7-day free trial. Cancel anytime.