Fetch Comments by User
curl --request GET \
--url https://api.sublay.io/v8/:projectId/users/:userId/comments \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.sublay.io/v8/:projectId/users/:userId/comments"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.sublay.io/v8/:projectId/users/:userId/comments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sublay.io/v8/:projectId/users/:userId/comments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.sublay.io/v8/:projectId/users/:userId/comments"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.sublay.io/v8/:projectId/users/:userId/comments")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/v8/:projectId/users/:userId/comments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{}
],
"pagination.nextCursor": {},
"pagination.hasMore": true
}User Endpoints
Fetch Comments by User
Get a user’s comment history — their comments at any depth, cursor-paginated
Fetch Comments by User
curl --request GET \
--url https://api.sublay.io/v8/:projectId/users/:userId/comments \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.sublay.io/v8/:projectId/users/:userId/comments"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.sublay.io/v8/:projectId/users/:userId/comments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sublay.io/v8/:projectId/users/:userId/comments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.sublay.io/v8/:projectId/users/:userId/comments"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.sublay.io/v8/:projectId/users/:userId/comments")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/v8/:projectId/users/:userId/comments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{}
],
"pagination.nextCursor": {},
"pagination.hasMore": true
}Requires the
comments bundle. A project without the comments bundle returns 403 database/tables-not-available. See Bundles.actingUserId. Without one (no user token, or a key without actingUserId) the request is anonymous: deleted and moderator-removed comments are left out, no block rule applies, isAuthorBlocked and isUnavailable are always false, and userReaction isn’t populated.
An unknown userId returns an empty page.
What’s in the list:
- Deleted comments are left out.
- Moderator-removed comments are left out of other people’s history. In the caller’s own history they are included in full, marked
moderationStatus: "removed". - Blocks: comments by a user the caller is block-edged with are left out by default (see
blockedFilter). Comments on an entity whose author has blocked the caller are left out too — except the caller’s own (see Your own comments on an unavailable entity).
Path Parameters
string
required
The Sublay user ID (UUID) of the user whose comments to list.
Query Parameters
Acting user
string
The user to read the history as. Takes effect only with a service or master key. A user token always reads as itself: naming its own ID changes nothing, and naming a different user returns
403 comment/unauthorized. On a request with neither a key nor a user token it is ignored, and the request stays anonymous. With a key, the rules below (own removed comments, blocks, blockedFilter, the isAuthorBlocked / isUnavailable flags and userReaction) apply from that user’s perspective.Filtering
string
Only comments on this entity.
string
Only comments on entities with this
sourceId. Applied whether or not include contains entity. On a project without the entities bundle, a request with sourceId returns an empty page.string
default:"exclude"
How comments by users the caller is block-edged with are treated.
"exclude" (default) leaves them out. "include-outbound-blocked" re-includes comments by users the caller themselves blocked — returned in full and marked isAuthorBlocked: true — and never surfaces content from users who blocked the caller. Has no effect when the moderation bundle is not installed.Pagination
number
default:"10"
Comments per batch. A whole number of at least
1 — 0, a negative number or a non-integer value returns 400 comment/invalid-query. Values above 100 are treated as 100.string
Leave it out on the first request (an empty
cursor is treated the same way), then pass pagination.nextCursor from the previous response. Must be sent with the same sortBy, sortDir and sortByReaction it was created under. Cursors work as on the thread endpoint — see Cursors.Sorting
string
default:"createdAt"
createdAt, top (raw count of sortByReaction) or controversial — the same meanings as on Fetch Many Comments. new and old are deprecated aliases for createdAt and receive a Deprecation response header.string
default:"desc"
asc or desc. Applies to every sort.string
default:"upvote"
With
sortBy=top only: the reaction to rank by (upvote, downvote, like, love, wow, sad, angry, funny). Sending it with any other sortBy returns 400.Optional associations
string
Comma-separated list of associations to include in each comment:
user— the comment author, with the avatar file URLsentity— the entity the comment is on, as its stored record: the fields an entity fetch computes or joins (such ascommentsCount,userReactionandnsfwEffective) are not included — see The included entity;nullwhen the entity isn’t available to the caller (for example, removed by a moderator) — the comment is still returnedspace— the entity’s space, asentity.space(also includesentity); whenentityisnullthere is no spaceparent—parentComment, for replies;nullwhen the parent no longer exists or is on another entitygrants— the reputation-grant summary
include never changes which comments are returned.Space-scoped reputation
This endpoint accepts the opt-in reputation params, resolved against each comment’s space. They add aspaceReputation field to each populated author user, alongside the always-present reputation total. Requires the reputation bundle. See the Reputation data model.
Response
{
"data": [ ...Comment[] ],
"pagination": { "nextCursor": "eyJ2Ijox…", "hasMore": true }
}
Comment[]
The user’s comments, in sort order. Each item is a Comment, with
isAuthorBlocked and isUnavailable flags. No comment carries nested replies.string | null
Pass this as
cursor to get the next batch. null when there’s nothing more.boolean
Whether more comments exist after this batch. Exact.
parentComment follows the same rules as everywhere else: a deleted or removed parent is a placeholder, and a parent whose author blocked the caller is a placeholder with isUnavailable: true.
Your own comments on an unavailable entity
When the caller lists their own history, their comments on an entity whose author has blocked them stay in the list, so they can still find and delete them. On those comments, everything belonging to the entity’s author is blanked:entity (which carries space) and parentComment are null when requested.
These comments are read-and-delete only: replying under them, reacting to them, and editing them are refused (404). They aren’t marked by a dedicated field. entity: null only means the entity isn’t available to the caller — it doesn’t say why, so it doesn’t identify these comments.
Error Responses
Unsupported parameter — 400
Unsupported parameter — 400
page isn’t supported — comments use cursor pagination.{
"error": "`page` isn't supported on this endpoint. Comments use cursor pagination: leave `cursor` out on the first request, then pass `pagination.nextCursor` from the previous response to get the next batch.",
"code": "comment/unsupported-param",
"param": "page"
}
Invalid user ID — 400
Invalid user ID — 400
Returned with code
comment/invalid-params when userId isn’t a valid UUID.Invalid query — 400
Invalid query — 400
Returned with code
comment/invalid-query for invalid values — for example an unknown include value, limit below 1 or not a whole number, or sortByReaction without sortBy=top.Invalid cursor — 400
Invalid cursor — 400
{
"error": "Invalid `cursor`. Pass `pagination.nextCursor` from a previous response unchanged, or leave `cursor` out to start from the beginning.",
"code": "comment/invalid-cursor"
}
Cursor from a different sort — 400
Cursor from a different sort — 400
{
"error": "This `cursor` was created under a different sort. Send the same `sortBy`, `sortDir` and `sortByReaction` as the request that returned it, or leave `cursor` out to start from the beginning.",
"code": "comment/cursor-sort-mismatch"
}
Acting as another user — 403
Acting as another user — 403
Returned when a request authenticated with a user token sends an
actingUserId other than that user’s own ID.{
"error": "Unauthorized",
"code": "comment/unauthorized"
}

