Docs

Analytics

Analytics and normalized metrics for Instagram media.

Read performance metrics for a published Instagram post. Requires instagram_business_manage_insights on the connection. Pass post as described in Analytics. Use the internal id for Onepostly posts. Use the native media id plus accountId for outside media.

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": "instagram",
        "externalPostId": "17895695668004550",
        "status": "ready",
        "metrics": {
          "impressions": 4200,
          "reach": 3100,
          "likes": 180,
          "comments": 12,
          "shares": 9,
          "saves": 44,
          "plays": 4200,
          "engagement": 245
        },
        "fetchedAt": "2026-08-25T10:00:00.000Z",
        "expiresAt": "2026-08-25T11:00:00.000Z",
        "error": null
      }
    ]
  }
}

Daily timeline

Day by day cumulative metrics per subject. Optional from and to bound the inclusive UTC date range. The default window covers the last 366 days.

const { timeline } = await analyticsApi.getAnalyticsTimeline({
  post: postId,
  from: "2026-08-01",
  to: "2026-08-28",
});
// timeline.subjects[].points[].day, metrics, delta

Each metrics object holds cumulative totals as captured on that UTC day. delta compares them against the previous stored day. A delta entry stays null when either side has no value. Days without a stored snapshot have no data. The API does not backfill them.

Outside posts

Media published outside Onepostly works the same way once it is 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://www.instagram.com/p/ABC123/" },
});
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 Instagram
impressionsImpressions or views, depending on product
reachReach when available
likesLike count
commentsComment count
sharesShare count
savesSave count
playsViews. Most useful for Reels
engagementTotal interactions, or the sum of likes plus comments plus shares plus saves

Missing values stay null. Available metrics vary by product. Feed posts, Reels and Stories each expose a different set, and Stories typically return fewer numbers.

Pending semantics

Errors

CodeCauseFix
NOT_PUBLISHEDDestination not published yetWait for publish
ANALYTICS_PERMISSIONConnection lacks analytics permissionReconnect the account
ANALYTICS_PENDINGMetrics not ready yetRetry later
ANALYTICS_FAILEDHard failure fetching metricsRetry. Contact support if it persists

See also