> **For coding agents and LLMs:** This is one Social Fetch marketing page (markdown export). For API orientation start with [`/llms.txt`](https://www.socialfetch.dev/llms.txt); for auth and crawl rules use [`/agents.txt`](https://www.socialfetch.dev/agents.txt); for every operation use [`/llms-endpoints.txt`](https://www.socialfetch.dev/llms-endpoints.txt).

## This page

- **On-site (HTML):** <https://www.socialfetch.dev/platforms/ko-fi/profiles-handle-posts>
- **Markdown (.mdx) URL:** <https://www.socialfetch.dev/platforms/ko-fi/profiles-handle-posts.mdx>

---

# Ko-fi Posts API

A creator's posts, images, messages and polls, 12 at a time, with filters for type, audience and tag.

`GET /v1/ko-fi/profiles/{handle}/posts` returns `data.posts`, newest first, 12 items a page. Each item has `id`, `type` (`post`, `image`, `message` or `poll`), `pinned`, `relativeTime`, `title`, `excerpt`, `url`, `slug`, `galleryItemId`, `image`, `likes`, `commentCount` and `access`. `access` is `members` or `supporters` when the feed shows a lock marker, and null when it does not; a public item is never labelled `public`. A locked item's `excerpt` and `image` are null when only a placeholder is public. `excerpt` is normalised to one line, so line breaks and non-breaking spaces do not appear in the JSON. The feed does not include an absolute date: use `relativeTime`, or fetch the post for `postedAt`.

Filter with `type` (`updates`, `posts`, `images`, `videos`, `audio`, `polls`), `access` (`public`, `supporters` or `members`) or `tag`. The `access` filter selects items the creator set for exactly that value: `supporters` returns supporter items only, not member items, and public items are returned when you ask for `public`. A tag uses letters, digits, underscores and hyphens only. Pass `page` (zero-based) or the opaque `cursor` from `page.nextCursor`; a cursor only works with the same filters. `data.id`, `data.handle` and `data.name` identify the creator. A missing creator is `not_found` with an empty list. A page past the end is `found` with `posts: []`. The last populated page can still report `hasMore: true`, and the next page may then be empty.

## Request

- **Endpoint:** `GET /v1/ko-fi/profiles/{handle}/posts`
- **Credits:** 1 credit
Failed requests are free
- **Input:** by handle, type or tag
- **Full reference:** [docs](https://www.socialfetch.dev/docs/api/v1/ko-fi/profiles/handle/posts/get)
- **Platform page:** [/platforms/ko-fi](https://www.socialfetch.dev/platforms/ko-fi)

## FAQ

### How do I get posts of one kind?

Set type to updates, posts, images, videos, audio or polls. For example type=images returns the image posts. The type filter is applied with the page, so the same page number means the same filtered page.

### How do I page through the feed?

Start with page=0, then keep requesting with page.nextCursor while page.hasMore is true. The cursor carries your filters, so a cursor from an unfiltered request is refused when you add a type or tag. page.nextPage gives the next number when you prefer paging by number. The last populated page can still carry a next cursor, so a following page that returns no posts means the feed is over.

### What do the access values mean?

On an item, access is members or supporters when the creator locked it, and null when it is public; there is no public value on an item. The access filter takes public, supporters or members and returns only items set to that exact audience. A post set for members is returned as members and is not included when you filter by supporters.

### Why is there no postedAt field?

The feed shows relative times such as 2 days ago, and the API does not invent an absolute date from them. Fetch GET /v1/ko-fi/posts/{slug} for postedAt and the full body.

### How many credits does a feed page 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. Each paginated page is a separate billed request.
