Bluesky hub

Bluesky profile posts API

Page recent public posts for a Bluesky handle — text, embeds, engagement metrics, and author context — in the shared Social Fetch response envelope.

GET /v1/bluesky/profiles/{handle}/posts

1 credit per successful request.

About this endpoint

Monitoring a Bluesky account usually means more than a profile card. You already know the handle; next you want the recent timeline: post text, like and reply counts, embeds, and stable web URLs you can store or open later. Standing up your own AT Protocol client works for a Bluesky-native app, but multi-network enrichment jobs often want the same auth, credits, and `{ data, meta }` shape they use for Instagram and X.

`GET /v1/bluesky/profiles/{handle}/posts` lists public posts for a handle (with or without a leading `@`). Send `x-api-key`, then read `data.lookupStatus` before you treat the page as usable. On `found`, `data.posts` holds the page rows and `data.page` carries `nextCursor` / `hasMore`. Optional query params: `cursor` from a previous page, and `userId` when you already have the Bluesky user id and want a faster resolve. Each post can include id (the `at://` URI), cid, public url, text, createdAt, indexedAt, author, metrics (likes, reposts, replies, quotes), and an embed when present.

This route pages a profile feed. A single post by URL is `GET /v1/bluesky/posts`. The profile card alone is `GET /v1/bluesky/profiles/{handle}`. Pricing is on the credit badge for this operation; bill from `meta.creditsCharged` on every response.

Bluesky profile posts API FAQ

How do I list Bluesky posts for a profile via API?

Call `GET /v1/bluesky/profiles/{handle}/posts` with your Social Fetch API key (`x-api-key`) and the Bluesky handle in the path. Read `data.lookupStatus`, then `data.posts` and `data.page`. Full parameters and examples are in the API docs linked from this page.

How much does the Bluesky profile posts endpoint cost?

Pricing is documented on the operation in the API registry (shown on this page). Confirm on every response with meta.creditsCharged — that field is the billing source of truth.

How does pagination work on Bluesky profile posts?

Each response includes `data.page.nextCursor` and `data.page.hasMore`. When `hasMore` is true, pass `nextCursor` as the `cursor` query param on the next request. Keep the same handle across pages. The cursor is opaque — do not invent or parse it.

What is the optional userId query param for?

If you already know the Bluesky user id for that handle, pass it as `userId` to speed up the request. It is optional; the handle alone is enough for a normal list call.

What fields are in each Bluesky post row?

Items can include id (stable `at://` URI), cid, public url, text, createdAt, indexedAt, author (handle, display name, avatar, verified flag), metrics (likes, reposts, replies, quotes), and embed (external link card, images, video, or quoted record) when Bluesky exposes them.

What happens for missing handles or empty feeds?

Branch on `data.lookupStatus`. Unknown handles resolve as `not_found` with an empty `posts` array. `found` can still return zero posts when the profile has no eligible items in the current page. Keep `meta.requestId` if you need support on a failed list call.

Profile posts vs single Bluesky post vs profile card?

Use this route to page a handle's public feed. Use `GET /v1/bluesky/posts` when you already have a post URL. Use `GET /v1/bluesky/profiles/{handle}` when you only need the profile card. They are separate operations on the Bluesky hub.

Do I need a Bluesky App Password to list profile posts?

No. You authenticate to Social Fetch with an API key. The route reads publicly visible post data; it does not act on behalf of a logged-in Bluesky user or require AT Protocol session credentials.