---
title: Read posts and analytics
description: Read feeds, single posts, likes, and current post metrics through the normalized API, with platform tabs covering scopes, limits, and native reads.
---

This page covers post and feed reads, post and account metrics, and
provider-native likes lists. See [Search](/reads/search),
[Social graph](/reads/graph), [Notifications](/reads/notifications), and
[Analytics reports](/reads/reports) for those separate surfaces.

## Normalized API

The facade returns provider-shaped `JsonObject` items in a `Page`:

```ts
const page = await social.posts.list(account, { limit: 25 });
const one = await social.posts.get(platformPostRef);
```

Pass `nextCursor` back unchanged with the same account and options. Cursors
are opaque. `posts.iterate(account, { maxPages, maxItems })` is lazy and
bounded.

The examples assume one client and one connected account for the adapter you
configure below:

```ts
const social = createSocial({ backend: adapter });
const account = connectedAccountRef({ backend: "default", platform: "x", accountId: "123" });
```

## Post metrics

```ts
const metrics = await social.analytics.getPostMetrics(platformPostRef);
const accountMetrics = await social.analytics.getAccountMetrics(account);
```

Both return `MetricValue[]`. An omitted metric means the provider did not
return it, not zero. Bounded date-range reports are covered in
[Analytics reports](/reads/reports).

## Platform support

### X

**Reads:** posts list, get, and iterate. **Metrics:** account and post, plus
native likes lists. **Access:** user scopes and your X API tier.

Use a user OAuth token. `appBearerToken` is for app-only operations such as
full-archive search, not user timelines.

```ts
import { x } from "@opencoredev/social-sdk/x";

const adapter = x({ auth: { userId: "123", accessToken: process.env.X_ACCESS_TOKEN! } });
```

Items may include `id`, `text`, `author_id`, timestamps, referenced tweets,
and `public_metrics`. User timeline, home timeline, mentions, liked posts,
and liking users are native operations: `userPosts`, `homeTimeline`,
`mentions`, `likedPosts`, and `likingUsers`. They need the matching X read
capability, user scopes, and an eligible API tier. Missing access raises
`missing_permission`; throttling raises `rate_limited`.

### Bluesky

**Reads:** author feed, list, and get. **Metrics:** account and post, plus
native likes lists. **Access:** `repo`. Feed page size is 1 to 100.

Use a PDS service and DID with an access JWT, or an OAuth session.

```ts
import { bluesky } from "@opencoredev/social-sdk/bluesky";

const adapter = bluesky({
  auth: {
    service: "https://bsky.social",
    did: "did:plc:example",
    accessJwt: process.env.BSKY_JWT!,
  },
});
```

Author-feed items keep their AT Protocol records and embeds. The normalized
post ref can carry the native `uri` and `cid`. Native `getLikes` lists users
who liked a post; `getActorLikes` lists posts an actor liked. `getAuthorFeed`,
`getPostThread`, and `getPosts` keep provider cursors. An invalid page size
raises `invalid_input`.

### Threads

**Reads:** list and get. **Metrics:** account and post. **Access:** user
token. Feed page size is 1 to 100.

Use the Threads user ID and a long-lived user access token.

```ts
import { threads } from "@opencoredev/social-sdk/threads";

const adapter = threads({ auth: { userId: "th_123", accessToken: process.env.THREADS_TOKEN! } });
```

Items contain `id`, `text`, `username`, `media_type`, `permalink`, and
`timestamp`. The `after` cursor is opaque. Threads has post and selected
account insights but no normalized likes list. Mentions, search, and post
details are native.

### Instagram

**Reads:** media list and get. **Metrics:** account and post insights.
**Access:** a professional account.

Use a professional account ID and access token, and pick Instagram Login or
Facebook Login. Business discovery and hashtag features need Facebook Login.

```ts
import { instagram } from "@opencoredev/social-sdk/instagram";

const adapter = instagram({
  auth: {
    accountId: "17840000000000000",
    accessToken: process.env.IG_TOKEN!,
    flavor: "instagram-login",
  },
});
```

Media includes Graph API fields such as ID, caption, media type, permalink,
timestamp, and URLs. Insights can include likes, comments, saves, shares,
and reach. Mentions, tagged media, and business discovery are native. The
`tags` mentions edge works with both login flavors.
Missing permissions raise `missing_permission`.

### YouTube

**Reads:** uploads and get. **Metrics:** channel and video statistics.
**Access:** an OAuth token and the channel ID.

Normalized posts are videos from the channel uploads feed.

```ts
import { youtube } from "@opencoredev/social-sdk/youtube";

const adapter = youtube({
  auth: { accessToken: process.env.YOUTUBE_TOKEN!, channelId: "UC_example" },
});
```

`posts.get` returns `snippet`, `status`, `statistics`, and processing
details. Statistics can include views, likes, and comments. Playlists and
playlist items are native. Reports need the separate
`https://www.googleapis.com/auth/yt-analytics.readonly` scope and a bounded
query. An inaccessible video raises an error instead of returning an empty item.

### LinkedIn

**Reads:** author feed and get. **Metrics:** post, and account for
organizations only. **Access:** `r_member_social` or `r_organization_social`.

Use a person or organization author URN and a monthly API version.

```ts
import { linkedin } from "@opencoredev/social-sdk/linkedin";

const adapter = linkedin({
  auth: { accessToken: process.env.LINKEDIN_TOKEN!, author: "urn:li:person:abc" },
  apiVersion: "202609",
});
```

Person authors need `r_member_social`; organization authors need
`r_organization_social`. The author feed uses an opaque offset cursor.
Organization account metrics need an administrator grant such as
`rw_organization_admin`. Member-profile account analytics are not supported.
Invalid URNs or API versions raise `invalid_config`.

### TikTok

**Reads:** video list and get. **Metrics:** account stats and per-video
counts. **Access:** Display API with `user.info.stats` and `video.list`.

TikTok reads use an access token, the creator's Open ID, and verified media
origins.

```ts
import { tiktok } from "@opencoredev/social-sdk/tiktok";

const adapter = tiktok({
  auth: { accessToken: process.env.TIKTOK_TOKEN!, openId: "open-id" },
  verifiedMediaOrigins: ["https://media.example.com"],
});
```

Video items include ID, creation time, title, description, dimensions, share
URL, and like, comment, share, and view counts. `getPostMetrics` reads the
same four counts through the video query endpoint and needs `video.list`.
Account counts need `user.info.stats`. TikTok has no normalized likes list.

## Errors and unsupported platforms

An unavailable capability raises `unsupported_capability`. Authentication
failures use `reconnect_required` or `unauthorized`; denied scopes use
`missing_permission`; bad cursors, references, or limits use `invalid_input`;
throttling uses `rate_limited`; and inaccessible resources can be `not_found`
or `gone`. Do not turn errors into empty pages or zero metrics.

Facebook has no post-read or analytics implementation in this SDK. Inspect
`social.capabilities()` before enabling a feature.
