curl --request POST \
--url https://api.example.com/search/global \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"q": "<string>",
"query": "<string>",
"sort_by": "relevance",
"sort_order": "asc",
"limit": 20,
"offset": 0,
"session_id": "<string>"
}
'import requests
url = "https://api.example.com/search/global"
payload = {
"q": "<string>",
"query": "<string>",
"sort_by": "relevance",
"sort_order": "asc",
"limit": 20,
"offset": 0,
"session_id": "<string>"
}
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({
q: '<string>',
query: '<string>',
sort_by: 'relevance',
sort_order: 'asc',
limit: 20,
offset: 0,
session_id: '<string>'
})
};
fetch('https://api.example.com/search/global', 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.example.com/search/global",
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([
'q' => '<string>',
'query' => '<string>',
'sort_by' => 'relevance',
'sort_order' => 'asc',
'limit' => 20,
'offset' => 0,
'session_id' => '<string>'
]),
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.example.com/search/global"
payload := strings.NewReader("{\n \"q\": \"<string>\",\n \"query\": \"<string>\",\n \"sort_by\": \"relevance\",\n \"sort_order\": \"asc\",\n \"limit\": 20,\n \"offset\": 0,\n \"session_id\": \"<string>\"\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.example.com/search/global")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"q\": \"<string>\",\n \"query\": \"<string>\",\n \"sort_by\": \"relevance\",\n \"sort_order\": \"asc\",\n \"limit\": 20,\n \"offset\": 0,\n \"session_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/search/global")
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 \"q\": \"<string>\",\n \"query\": \"<string>\",\n \"sort_by\": \"relevance\",\n \"sort_order\": \"asc\",\n \"limit\": 20,\n \"offset\": 0,\n \"session_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"session_id": "<string>",
"pagination": {
"offset": 123,
"limit": 123,
"total": 123
},
"results": [
{
"entity_type": "<string>",
"entity_id": "<string>",
"title": "<string>",
"score": 123,
"subtitle": "<string>",
"url": "<string>",
"metadata": {}
}
]
}{
"error": {
"code": "INVALID_REQUEST",
"message": "<string>",
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"details": {}
}
}{
"error": {
"code": "INVALID_REQUEST",
"message": "<string>",
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"details": {}
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}{
"error": {
"code": "INVALID_REQUEST",
"message": "<string>",
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"details": {}
}
}Global search
Unified search across all entity types — projects, assets, data connections, catalog entities (databases, schemas, tables, columns), files, artifacts, agents, and models. Results are filtered to entities the authenticated user can access.
Query modes (set via the mode field):
-
semantic(default): Plain natural language.qis run through BM25 and, when an embedding service is configured, also vectorised for hybrid RRF ranking. Best for conversational queries. -
structured: Elasticsearch-style query string inquery. Parsed by the Lark grammar and translated to SQL predicates against thesearch_attributesJSONB column and the ParadeDB BM25 index. Supports field:value, wildcards, boolean AND/OR/NOT, exists checks, tag filtering, and extension field comparisons. Replaces the retiredGET /search/metadataendpoint. -
hybrid: Both legs simultaneously.qdrives semantic ranking;queryapplies structural constraints. Results are merged via Reciprocal Rank Fusion (RRF).
Pagination: pass session_id from the first response on subsequent pages to reuse the scope session and avoid re-running the OpenFGA ListObjects fan-out.
Structured query syntax examples:
service.name:mysql AND tags.tagFQN:PII* — PII-tagged tables in a MySQL service
NOT _exists_:owners AND entity_type:table — tables missing owners
NOT _exists_:columns.description — tables with undescribed columns
extension.is_pii_tagged:1 AND databaseSchema.name:public — PII tables in public schema
(tags.tagFQN:SENSITIVITY_TAGS.Confidential OR tags.tagFQN:SENSITIVITY_TAGS.Restricted) AND service.name:snowflake — confidential or restricted Snowflake entities
curl --request POST \
--url https://api.example.com/search/global \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"q": "<string>",
"query": "<string>",
"sort_by": "relevance",
"sort_order": "asc",
"limit": 20,
"offset": 0,
"session_id": "<string>"
}
'import requests
url = "https://api.example.com/search/global"
payload = {
"q": "<string>",
"query": "<string>",
"sort_by": "relevance",
"sort_order": "asc",
"limit": 20,
"offset": 0,
"session_id": "<string>"
}
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({
q: '<string>',
query: '<string>',
sort_by: 'relevance',
sort_order: 'asc',
limit: 20,
offset: 0,
session_id: '<string>'
})
};
fetch('https://api.example.com/search/global', 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.example.com/search/global",
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([
'q' => '<string>',
'query' => '<string>',
'sort_by' => 'relevance',
'sort_order' => 'asc',
'limit' => 20,
'offset' => 0,
'session_id' => '<string>'
]),
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.example.com/search/global"
payload := strings.NewReader("{\n \"q\": \"<string>\",\n \"query\": \"<string>\",\n \"sort_by\": \"relevance\",\n \"sort_order\": \"asc\",\n \"limit\": 20,\n \"offset\": 0,\n \"session_id\": \"<string>\"\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.example.com/search/global")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"q\": \"<string>\",\n \"query\": \"<string>\",\n \"sort_by\": \"relevance\",\n \"sort_order\": \"asc\",\n \"limit\": 20,\n \"offset\": 0,\n \"session_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/search/global")
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 \"q\": \"<string>\",\n \"query\": \"<string>\",\n \"sort_by\": \"relevance\",\n \"sort_order\": \"asc\",\n \"limit\": 20,\n \"offset\": 0,\n \"session_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"session_id": "<string>",
"pagination": {
"offset": 123,
"limit": 123,
"total": 123
},
"results": [
{
"entity_type": "<string>",
"entity_id": "<string>",
"title": "<string>",
"score": 123,
"subtitle": "<string>",
"url": "<string>",
"metadata": {}
}
]
}{
"error": {
"code": "INVALID_REQUEST",
"message": "<string>",
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"details": {}
}
}{
"error": {
"code": "INVALID_REQUEST",
"message": "<string>",
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"details": {}
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}{
"error": {
"code": "INVALID_REQUEST",
"message": "<string>",
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"details": {}
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Request body for POST /search/global.
The execution mode is inferred automatically from the fields provided:
Semantic — provide q only. Natural language, BM25 + optional vector RRF::
{"q": "tables with customer revenue data"}
Structured — provide query only. Elasticsearch-style predicates::
{"query": "service.name:mysql AND tags.tagFQN:PII*"}
Hybrid — provide both. q drives BM25/vector; query applies hard constraints::
{"q": "customer revenue", "query": "service.name:snowflake AND NOT _exists_:owners"}
Structured query syntax
+-----------------------------------------+----------------------------------------------+
| Expression | Meaning |
+=========================================+==============================================+
| users | BM25 full-text match on embedded_text |
+-----------------------------------------+----------------------------------------------+
| name:users | Exact name match |
+-----------------------------------------+----------------------------------------------+
| name:user* | Trailing-wildcard name match |
+-----------------------------------------+----------------------------------------------+
| service.name:"mysql" | Filter by data source name |
+-----------------------------------------+----------------------------------------------+
| database.name:"prod" | Filter by database name |
+-----------------------------------------+----------------------------------------------+
| databaseSchema.name:"public" | Filter by schema name |
+-----------------------------------------+----------------------------------------------+
| tags.tagFQN:PII* | Tag FQN prefix match |
+-----------------------------------------+----------------------------------------------+
| tags.tagFQN:SENSITIVITY_TAGS.Conf* | Exact tag FQN prefix |
+-----------------------------------------+----------------------------------------------+
| extension.is_pii_tagged:1 | Boolean extension field (1/true/0/false) |
+-----------------------------------------+----------------------------------------------+
| extension.is_sensitivity_tagged:0 | Entities not sensitivity-tagged |
+-----------------------------------------+----------------------------------------------+
| _exists_:description | Has a description |
+-----------------------------------------+----------------------------------------------+
| NOT _exists_:description | Missing description |
+-----------------------------------------+----------------------------------------------+
| NOT _exists_:owners | Missing owners |
+-----------------------------------------+----------------------------------------------+
| NOT _exists_:columns.description | Has columns missing descriptions |
+-----------------------------------------+----------------------------------------------+
| _exists_:columns.tags.tagFQN:PII* | Has PII-tagged columns |
+-----------------------------------------+----------------------------------------------+
| entity_type:table | Restrict to a specific entity type |
+-----------------------------------------+----------------------------------------------+
| entity_id:snowflake-prod.analytics.* | FQN prefix scope (all children) |
+-----------------------------------------+----------------------------------------------+
| A AND B, A OR B, NOT A | Boolean operators |
+-----------------------------------------+----------------------------------------------+
| (A OR B) AND C | Grouping |
+-----------------------------------------+----------------------------------------------+
Natural language search query. Passed to the BM25 index and (when an embedding service is configured) vectorised for the vector leg of RRF. Example: 'tables containing customer revenue data'
1Elasticsearch-style query string. Parsed by the Lark grammar and translated to SQL predicates against search_attributes JSONB and the ParadeDB BM25 index. Example: 'service.name:mysql AND tags.tagFQN:PII* AND NOT exists:owners'
1Result ordering. RELEVANCE (default): ranked by BM25/RRF score. NAME: alphabetical by title. CREATED_AT: by creation time. RELEVANCE is ignored for STRUCTURED mode with no bare-word terms.
relevance, name, created_at Sort direction for NAME and CREATED_AT. ASC (default) or DESC. Has no effect when sort_by=RELEVANCE — relevance scores are always ranked highest-first.
asc, desc Page size (1–100, default 20)
1 <= x <= 100Pagination offset (default 0)
x >= 0Permission session token from a previous response. Pass this on subsequent paginated requests to reuse the scope materialisation and avoid re-running the OpenFGA ListObjects fan-out on every page.
Response
Successful Response
Response body for POST /search/global.
Pass this on subsequent paginated requests to reuse the scope session and avoid re-running the OpenFGA ListObjects fan-out. Sessions expire after 30 minutes of inactivity.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Was this page helpful?

