> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sublay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Fetch many comments

> Fetch one level of a comment thread, cursor-paginated, with optional nested replies

export const SpaceReputationParams = ({variant = "context", field = "path"}) => {
  const isUser = variant === "user";
  return <>
      <ParamField {...{
    [field]: "spaceReputation",
    type: "object"
  }}>
        Opt-in. Adds a <code>spaceReputation</code> number to each returned user,
        scoped to a single space. Requires the <code>reputation</code> bundle.
        The <code>reputation</code> total is always present regardless;{" "}
        <code>spaceReputation</code> is purely additive and only appears when you
        pass this object. <strong>This object is the primary form</strong> — it
        replaces the deprecated flat props below. See the{" "}
        <a href="/v8/data-models/reputation">Reputation data model</a> for the
        full contract.

        <Expandable title="spaceReputation">
          {isUser ? <ParamField name="spaceId" type="string | &quot;none&quot;" required>
              Which bucket to read. A space <strong><code>&lt;uuid&gt;</code></strong> reads that
              space's bucket; <strong><code>"none"</code></strong> reads the
              project-general (space-less) bucket.{" "}
              <strong><code>"context"</code> is rejected (400)</strong> on this
              endpoint — there is no space context to derive. The empty string
              and the legacy <code>general</code> / <code>null</code> aliases are
              also rejected. Missing buckets read as <code>0</code>.
            </ParamField> : <ParamField name="spaceId" type="string | &quot;none&quot; | &quot;context&quot;" required>
              Which bucket to read. One of: a space <strong><code>&lt;uuid&gt;</code></strong>{" "}
              (that space's bucket), <strong><code>"none"</code></strong> (the
              project-general, space-less bucket), or{" "}
              <strong><code>"context"</code></strong> (the space derived from the
              request context — resolved per-row on lists, or the single space on
              member/team/conversation surfaces). The empty string and the legacy{" "}
              <code>general</code> / <code>null</code> aliases are rejected (400).
              Missing buckets read as <code>0</code>.
            </ParamField>}
          <ParamField name="includeDescendants" type="boolean">
            Only honored when <code>spaceId</code> is an explicit space <code>&lt;uuid&gt;</code>.
            When <code>true</code>, <code>spaceReputation</code> is the{" "}
            <strong>subtree sum</strong> — the named space plus all of its
            descendant spaces (the root space's own bucket included). Ignored for{" "}
            <code>"none"</code>; not allowed with <code>"context"</code>.
          </ParamField>
        </Expandable>
      </ParamField>

      {isUser ? <ParamField {...{
    [field]: "spaceReputationId",
    type: "string",
    deprecated: true
  }}>
          <strong>Deprecated</strong> — use the <code>spaceReputation</code>{" "}
          object instead. The flat form of <code>spaceReputation.spaceId</code>.
          Still accepted (the object wins if both are passed); removal is a later
          major version. Accepts a space <code>&lt;uuid&gt;</code> or <code>"none"</code> only —{" "}
          <code>"context"</code> is rejected (400) on this endpoint.
        </ParamField> : <ParamField {...{
    [field]: "spaceReputationId",
    type: "string",
    deprecated: true
  }}>
          <strong>Deprecated</strong> — use the <code>spaceReputation</code>{" "}
          object instead. The flat form of <code>spaceReputation.spaceId</code>.
          Still accepted (the object wins if both are passed); removal is a later
          major version. Accepts a space <code>&lt;uuid&gt;</code>, <code>"none"</code>, or{" "}
          <code>"context"</code>.
        </ParamField>}

      <ParamField {...{
    [field]: "spaceReputationDescendants",
    type: "boolean",
    deprecated: true
  }}>
        <strong>Deprecated</strong> — use{" "}
        <code>spaceReputation.includeDescendants</code> instead. The flat form,
        only honored alongside an explicit <code>spaceReputationId</code> <code>&lt;uuid&gt;</code>.
      </ParamField>
    </>;
};

## Overview

`useFetchManyComments` returns a function that fetches one level of a comment thread ([`GET /comments`](/v8/api-reference/comments/fetch-many-comments)): an entity's top-level comments (`entityId`) or a comment's direct replies (`parentId`). It's the fetch function behind `useEntityComments` and `useReplies`. Use it directly when you need full control over a thread request.

For a user's comments across entities, use [`useFetchCommentsByUserId`](/v8/hooks/comments/use-fetch-comments-by-user-id).

## Usage Example

```tsx theme={null}
import { useFetchManyComments, type Comment } from "@sublay/react-js";
import { useEffect, useState } from "react";

function TopComments({ entityId }: { entityId: string }) {
  const fetchComments = useFetchManyComments();
  const [comments, setComments] = useState<Comment[]>([]);
  const [cursor, setCursor] = useState<string | null>(null);

  useEffect(() => {
    fetchComments({
      entityId,
      sortBy: "top",
      limit: 10,
      include: "user",
      replyDepth: 1, // also bring each comment's first replies
      replyLimit: 2,
    }).then((res) => {
      setComments(res.data);
      setCursor(res.pagination.nextCursor);
    });
  }, [entityId]);

  const loadMore = async () => {
    if (!cursor) return;
    const res = await fetchComments({ entityId, sortBy: "top", limit: 10, cursor, include: "user" });
    setComments((prev) => [...prev, ...res.data]);
    setCursor(res.pagination.nextCursor);
  };

  return (
    <>
      <ul>{comments.map((c) => <li key={c.id}>{c.content}</li>)}</ul>
      {cursor && <button onClick={loadMore}>Load more</button>}
    </>
  );
}
```

## Parameters

One of `entityId` or `parentId` is required.

<ParamField path="entityId" type="string">
  Fetch this entity's top-level comments.
</ParamField>

<ParamField path="parentId" type="string">
  Fetch this comment's direct replies.
</ParamField>

<ParamField path="limit" type="number">
  How many comments at the level being fetched. Server default `10`, max `100`.
</ParamField>

<ParamField path="cursor" type="string | null">
  `pagination.nextCursor` from the previous response. Omit for the first page. Send the same sort as the request that returned it.
</ParamField>

<ParamField path="sortBy" type="CommentsSortByOptions">
  `"createdAt"`, `"top"` (raw count of `sortByReaction`) or `"controversial"`. Server default `"createdAt"`. `"new"` / `"old"` are deprecated aliases for `"createdAt"`.
</ParamField>

<ParamField path="sortDir" type="&#x22;asc&#x22; | &#x22;desc&#x22;">
  Applies to every sort. Server default `"desc"`.
</ParamField>

<ParamField path="sortByReaction" type="ReactionType">
  With `sortBy: "top"` only: the reaction to rank by. Server default `"upvote"`.
</ParamField>

<ParamField path="replyDepth" type="number">
  Levels of replies to nest under each returned comment (`0`–`5`). Server default `0`.
</ParamField>

<ParamField path="replyLimit" type="number">
  Replies per comment in the nested levels (at least `1`). Server default `3`.
</ParamField>

<ParamField path="replySortBy" type="CommentReplySortByOptions">
  Sort for the nested levels: `"createdAt"`, `"top"` or `"controversial"`. Defaults to `sortBy`.
</ParamField>

<ParamField path="replySortDir" type="&#x22;asc&#x22; | &#x22;desc&#x22;">
  Sort direction for the nested levels. Defaults to `sortDir`.
</ParamField>

<ParamField path="replySortByReaction" type="ReactionType">
  The reaction the nested levels rank by, when their sort is `"top"`.
</ParamField>

<ParamField path="include" type="&#x22;user&#x22; | &#x22;grants&#x22; | (&#x22;user&#x22; | &#x22;grants&#x22;)[]">
  Related data to populate, at every level.
</ParamField>

<SpaceReputationParams variant="context" field="path" />

A request can return at most 500 comments, nested replies included — see [Request size limit](/v8/api-reference/comments/fetch-many-comments#request-size-limit).

## Returns

A `Promise<CursorPaginatedResponse<Comment>>`:

<ResponseField name="data" type="Comment[]">
  The comments at the requested level. With `replyDepth` above `0`, each carries nested `replies` (`{ data, pagination }`). When `spaceReputation` is requested, each embedded author carries an added `spaceReputation` number. See [Reputation](/v8/data-models/reputation).
</ResponseField>

<ResponseField name="pagination.nextCursor" type="string | null">
  Pass as `cursor` to get the next page. `null` when there's nothing more.
</ResponseField>

<ResponseField name="pagination.hasMore" type="boolean">
  Whether more comments exist after this page.
</ResponseField>

See [Fetch Many Comments](/v8/api-reference/comments/fetch-many-comments) for placeholders, block flags and how to continue nested replies.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.