Analytics & Engagement
Read post analytics for X with GET /v1/analytics, and retweet, bookmark and follow with the Twitter engagement endpoints.
By the end of this page you can read impressions, likes, comments, shares, saves, clicks and views for your X posts. You can also retweet, bookmark and follow from a connected X account.
Before you start
You need a connected X account (accountId).
Every X read and write is billed at X's pass-through rate, listed on X API usage.
Read post analytics
Call GET /v1/analytics?platform=twitter with a date range (Get post analytics). fromDate defaults to 90 days ago, and the range is at most 366 days.
Impressions, likes, comments, shares, clicks and saves (X's bookmark count) are available on every post.
Views. views is X's media view count, which X publishes on the media object alone. A post with a video or an animated GIF reports it; a text or image post reports 0.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: analytics } = await zernio.analytics.getAnalytics({
query: { platform: 'twitter', fromDate: '2026-08-01', toDate: '2026-08-31' }
});
console.log(analytics.posts);Response (200), one entry per post:
{
"posts": [
{
"_id": "65f1c0a9e2b5af0012ab34cd",
"platform": "twitter",
"status": "published",
"publishedAt": "2026-08-14T10:00:05Z",
"platformPostUrl": "https://twitter.com/acmecorp/status/1852634789012345678",
"analytics": {
"impressions": 15420,
"likes": 342,
"comments": 28,
"shares": 45,
"saves": 63,
"clicks": 189,
"views": 9820,
"engagementRate": 2.78
}
}
]
}Retweet, bookmark or follow
Call POST /v1/twitter/retweet, POST /v1/twitter/bookmark or POST /v1/twitter/follow with accountId and the target (Twitter engagement).
X allows 50 requests per 15-minute window on each of them. Retweets also count against the 300 posts per 3 hours that post creation uses.
Bookmarks need the bookmark.write scope, and follows the follows.write scope. A follow request to a protected account comes back with pending_follow: true.
const { data: retweet } = await zernio.twitterengagement.retweetPost({
body: { accountId: '66b2e19d8c3f5a7e9d0b1c2d', tweetId: '1748391029384756102' }
});
console.log(retweet.retweeted);Response (200):
{
"status": "success",
"tweetId": "1748391029384756102",
"retweeted": true,
"platform": "twitter"
}Bookmark and follow take the same body and answer in the same shape, with their own boolean.
Each action has a DELETE on the same path that undoes it, with the ids as query parameters. The undo returns the same body with the boolean set to false.
| Action | Call | Body | Boolean in the response | Undo |
|---|---|---|---|---|
| Retweet | POST /v1/twitter/retweet | accountId, tweetId | retweeted | DELETE /v1/twitter/retweet?accountId=&tweetId= |
| Bookmark | POST /v1/twitter/bookmark | accountId, tweetId | bookmarked | DELETE /v1/twitter/bookmark?accountId=&tweetId= |
| Follow | POST /v1/twitter/follow | accountId, targetUserId | following, plus pending_follow | DELETE /v1/twitter/follow?accountId=&targetUserId= |
To find posts to act on:
- Search recent tweets covers the last 7 days with X's search operators.
- Look up a tweet resolves any post id or URL to its text, author and public metrics.
If it fails
A 403 on an engagement endpoint means X refused the action for this account. For example, the OAuth token lacks the bookmark.write or follows.write scope, or the account is suspended:
{
"error": "X rejected the request (e.g. suspended account, missing OAuth scope)",
"type": "platform_error",
"code": "platform_api_error",
"platform": "twitter"
}Reconnect the account so the consent screen grants every scope on the X page, then retry.
A 404 means accountId is not one of your connected accounts. Error handling covers the envelope.
Related
- Get post analytics: every query parameter and the single-post lookup.
- Twitter engagement: retweet, bookmark, follow, search and look up.
- Rate limits: how Zernio handles a
429from X. - X API usage: what each read and write costs.