Docs

Analytics

Analytics and normalized metrics for X posts.

Read performance metrics for a published X post. Requires tweet.read on the connection. Pass post as described in Analytics. Use the internal id for Onepostly posts. Use the native tweet id plus accountId for outside tweets.

Request

import { Configuration, AnalyticsApi } from "@onepostly/sdk";

const analyticsApi = new AnalyticsApi(
  new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY }),
);

const { analytics } = await analyticsApi.getAnalytics({ post: postId });
console.log(analytics.subjects);

Response

{
  "analytics": {
    "post": "POST_ID",
    "status": "ready",
    "fetchedAt": "2026-08-25T10:00:00.000Z",
    "subjects": [
      {
        "scope": "destination",
        "subjectId": "DEST_ID",
        "accountId": "ACCOUNT_ID",
        "platform": "x",
        "externalPostId": "1960956321831854280",
        "status": "ready",
        "metrics": {
          "impressions": 1200,
          "reach": null,
          "likes": 42,
          "comments": 3,
          "shares": 11,
          "saves": 5,
          "plays": 1200,
          "engagement": 61
        },
        "fetchedAt": "2026-08-25T10:00:00.000Z",
        "expiresAt": null,
        "error": null
      }
    ]
  }
}

Outside posts

Tweets published outside Onepostly work the same way once they are synced. Sync by URL then read analytics with the native id plus accountId. Omit url and postId to refresh the recent posts of the account in bulk.

const { found, post } = await posts.syncExternal({
  syncExternalBody: { accountId, url: "https://x.com/you/status/1960956321831854280" },
});
if (!found || !post) throw new Error("Post not found on the account.");

const { analytics } = await analyticsApi.getAnalytics({
  post: post.externalPostId,
  accountId,
});

Normalized fields

FieldMeaning on X
impressionsImpression count
reachAlways null. X does not expose it
likesLike count
commentsReply count
sharesRetweets plus quotes
savesBookmark count
playsSame as impressions when present
engagementLikes plus comments plus shares plus saves

Missing values stay null.

Notes

A fresh post usually reads pending until X makes metrics available. Retry later. Metrics may lag real time. See Analytics Freshness. Daily timelines are not available for X. Read the analytics endpoint instead. X reads bill the wallet like other X usage.

Errors

CodeCauseFix
MISSING_EXTERNAL_IDDestination not published yetWait for publish
ANALYTICS_PERMISSIONConnection lacks tweet.readReconnect the account
X_OUT_OF_CREDITSX developer account has no creditsContact support
INSUFFICIENT_WALLETWallet balance ran outTop up in Settings → Billing
ANALYTICS_FAILEDTweet deleted or unavailableCheck that the tweet still exists
TIMELINE_UNSUPPORTEDDaily timelines are not available for XRead the analytics endpoint instead

See also