Search Content
curl --request POST \
--url https://api.sublay.io/v8/:projectId/search/content \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "<string>",
"sourceTypes": [
"<string>"
],
"spaceId": "<string>",
"includeChildSpaces": true,
"conversationId": "<string>",
"limit": 123
}
'import requests
url = "https://api.sublay.io/v8/:projectId/search/content"
payload = {
"query": "<string>",
"sourceTypes": ["<string>"],
"spaceId": "<string>",
"includeChildSpaces": True,
"conversationId": "<string>",
"limit": 123
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '<string>',
sourceTypes: ['<string>'],
spaceId: '<string>',
includeChildSpaces: true,
conversationId: '<string>',
limit: 123
})
};
fetch('https://api.sublay.io/v8/:projectId/search/content', 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/search/content",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => '<string>',
'sourceTypes' => [
'<string>'
],
'spaceId' => '<string>',
'includeChildSpaces' => true,
'conversationId' => '<string>',
'limit' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sublay.io/v8/:projectId/search/content"
payload := strings.NewReader("{\n \"query\": \"<string>\",\n \"sourceTypes\": [\n \"<string>\"\n ],\n \"spaceId\": \"<string>\",\n \"includeChildSpaces\": true,\n \"conversationId\": \"<string>\",\n \"limit\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sublay.io/v8/:projectId/search/content")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"<string>\",\n \"sourceTypes\": [\n \"<string>\"\n ],\n \"spaceId\": \"<string>\",\n \"includeChildSpaces\": true,\n \"conversationId\": \"<string>\",\n \"limit\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/v8/:projectId/search/content")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"<string>\",\n \"sourceTypes\": [\n \"<string>\"\n ],\n \"spaceId\": \"<string>\",\n \"includeChildSpaces\": true,\n \"conversationId\": \"<string>\",\n \"limit\": 123\n}"
response = http.request(request)
puts response.read_bodySearch Endpoints
Search Content
Semantic search over entities, comments, and messages
Search Content
curl --request POST \
--url https://api.sublay.io/v8/:projectId/search/content \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "<string>",
"sourceTypes": [
"<string>"
],
"spaceId": "<string>",
"includeChildSpaces": true,
"conversationId": "<string>",
"limit": 123
}
'import requests
url = "https://api.sublay.io/v8/:projectId/search/content"
payload = {
"query": "<string>",
"sourceTypes": ["<string>"],
"spaceId": "<string>",
"includeChildSpaces": True,
"conversationId": "<string>",
"limit": 123
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '<string>',
sourceTypes: ['<string>'],
spaceId: '<string>',
includeChildSpaces: true,
conversationId: '<string>',
limit: 123
})
};
fetch('https://api.sublay.io/v8/:projectId/search/content', 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/search/content",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => '<string>',
'sourceTypes' => [
'<string>'
],
'spaceId' => '<string>',
'includeChildSpaces' => true,
'conversationId' => '<string>',
'limit' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.sublay.io/v8/:projectId/search/content"
payload := strings.NewReader("{\n \"query\": \"<string>\",\n \"sourceTypes\": [\n \"<string>\"\n ],\n \"spaceId\": \"<string>\",\n \"includeChildSpaces\": true,\n \"conversationId\": \"<string>\",\n \"limit\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sublay.io/v8/:projectId/search/content")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"<string>\",\n \"sourceTypes\": [\n \"<string>\"\n ],\n \"spaceId\": \"<string>\",\n \"includeChildSpaces\": true,\n \"conversationId\": \"<string>\",\n \"limit\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/v8/:projectId/search/content")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"<string>\",\n \"sourceTypes\": [\n \"<string>\"\n ],\n \"spaceId\": \"<string>\",\n \"includeChildSpaces\": true,\n \"conversationId\": \"<string>\",\n \"limit\": 123\n}"
response = http.request(request)
puts response.read_bodyPerforms vector-similarity search over project content (entities, comments, and chat messages) using AI embeddings. Returns the most semantically relevant results for the given query.
Requires a paid plan with semantic search enabled.
Authentication required. Send a user’s access token as
Each result includes:
Authorization: Bearer <token> — missing token → 401, invalid/expired token → 403 (refresh and retry). A service or master key is accepted too; such a request has no signed-in user, so the per-user filtering under What’s left out doesn’t apply to it.
Body Parameters
string
required
The natural language search query.
string[]
default:"[\"entity\", \"comment\", \"message\"]"
Content types to search. Any combination of
entity, comment, message.string
Restrict search to a specific space.
boolean
default:"false"
Only applies with a
spaceId. When true, the search also includes every space nested under it — children, grandchildren, the whole subtree at any depth — not just the named space. Ignored without a spaceId.string
Restrict message search to a specific conversation.
number
default:"20"
Maximum number of results to return. A whole number from
1 to 50, sent as a JSON number. A value outside that range is rejected with 400 search/invalid-body — a limit above 50 isn’t lowered to 50.Query Parameters
Space-scoped reputation
This endpoint has a space in context, so it accepts the opt-in reputation params. They add aspaceReputation field to each result record’s populated user, alongside the always-present reputation total. Requires the reputation bundle. See the Reputation data model for the full contract.
Response
Returns an array of result objects ordered by similarity (highest first):[
{
"sourceType": "entity",
"similarity": 0.87,
"record": { ...Entity | Comment | ChatMessage... }
}
]
sourceType— one of"entity","comment", or"message", indicating which type of record was matched.similarity— cosine similarity score between the query and the matched content.record— the fully populated entity, comment, or chat message object. Entity records carrycommentsCount. A record’suseris the author’s public User — no email or other private fields.
What’s left out
Comments their author deleted are never returned. Comments a moderator removed are never returned either — to anyone, including the removed comment’s author and requests made with a service or master key. Results are also filtered for the signed-in user (with themoderation bundle installed):
- Content by users they are block-edged with, in either direction, is left out.
- Comments on an entity whose author has blocked them are left out — their own comments there included.
Error Responses
Authentication Required — 401 / 403
Authentication Required — 401 / 403
The endpoint requires a user token or a service or master key. A missing token returns a bare
401; an invalid or expired token returns a bare 403 — refresh the access token and retry.Invalid Body — 400
Invalid Body — 400
Returned when the body fails validation:
query is missing or empty, limit isn’t a whole number from 1 to 50, sourceTypes contains a value other than entity, comment or message, spaceId or conversationId isn’t a UUID, or includeChildSpaces isn’t a boolean.{ "error": "limit: Too big: expected number to be <=50", "code": "search/invalid-body" }
Plan Required — 403
Plan Required — 403
{ "error": "Semantic search requires a paid plan", "code": "project/plan-required" }

