Search Entities
Search entities with advanced filtering, sorting, and pagination. Supports filtering by entity type, name search, field filters (with OR between filter groups and AND within groups), and custom sorting.
curl --request POST \
--url https://public.api.serval.com/v2/entities/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"teamId": "<string>",
"entityTypeId": "<string>",
"entityTypeKey": "<string>",
"filterGroups": [
{
"filters": [
{
"boolValue": {
"eq": true
},
"fieldId": "<string>",
"fieldKey": "<string>"
}
],
"sourceFilter": {
"eq": "<string>",
"ne": "<string>"
}
}
],
"fieldSorts": [
{
"entitySource": {},
"descending": true
}
],
"pageSize": 123,
"pageToken": "<string>",
"key": "<string>",
"includeArchived": true
}
'import requests
url = "https://public.api.serval.com/v2/entities/search"
payload = {
"teamId": "<string>",
"entityTypeId": "<string>",
"entityTypeKey": "<string>",
"filterGroups": [
{
"filters": [
{
"boolValue": { "eq": True },
"fieldId": "<string>",
"fieldKey": "<string>"
}
],
"sourceFilter": {
"eq": "<string>",
"ne": "<string>"
}
}
],
"fieldSorts": [
{
"entitySource": {},
"descending": True
}
],
"pageSize": 123,
"pageToken": "<string>",
"key": "<string>",
"includeArchived": True
}
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({
teamId: '<string>',
entityTypeId: '<string>',
entityTypeKey: '<string>',
filterGroups: [
{
filters: [{boolValue: {eq: true}, fieldId: '<string>', fieldKey: '<string>'}],
sourceFilter: {eq: '<string>', ne: '<string>'}
}
],
fieldSorts: [{entitySource: {}, descending: true}],
pageSize: 123,
pageToken: '<string>',
key: '<string>',
includeArchived: true
})
};
fetch('https://public.api.serval.com/v2/entities/search', 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://public.api.serval.com/v2/entities/search",
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([
'teamId' => '<string>',
'entityTypeId' => '<string>',
'entityTypeKey' => '<string>',
'filterGroups' => [
[
'filters' => [
[
'boolValue' => [
'eq' => true
],
'fieldId' => '<string>',
'fieldKey' => '<string>'
]
],
'sourceFilter' => [
'eq' => '<string>',
'ne' => '<string>'
]
]
],
'fieldSorts' => [
[
'entitySource' => [
],
'descending' => true
]
],
'pageSize' => 123,
'pageToken' => '<string>',
'key' => '<string>',
'includeArchived' => true
]),
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://public.api.serval.com/v2/entities/search"
payload := strings.NewReader("{\n \"teamId\": \"<string>\",\n \"entityTypeId\": \"<string>\",\n \"entityTypeKey\": \"<string>\",\n \"filterGroups\": [\n {\n \"filters\": [\n {\n \"boolValue\": {\n \"eq\": true\n },\n \"fieldId\": \"<string>\",\n \"fieldKey\": \"<string>\"\n }\n ],\n \"sourceFilter\": {\n \"eq\": \"<string>\",\n \"ne\": \"<string>\"\n }\n }\n ],\n \"fieldSorts\": [\n {\n \"entitySource\": {},\n \"descending\": true\n }\n ],\n \"pageSize\": 123,\n \"pageToken\": \"<string>\",\n \"key\": \"<string>\",\n \"includeArchived\": true\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://public.api.serval.com/v2/entities/search")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"teamId\": \"<string>\",\n \"entityTypeId\": \"<string>\",\n \"entityTypeKey\": \"<string>\",\n \"filterGroups\": [\n {\n \"filters\": [\n {\n \"boolValue\": {\n \"eq\": true\n },\n \"fieldId\": \"<string>\",\n \"fieldKey\": \"<string>\"\n }\n ],\n \"sourceFilter\": {\n \"eq\": \"<string>\",\n \"ne\": \"<string>\"\n }\n }\n ],\n \"fieldSorts\": [\n {\n \"entitySource\": {},\n \"descending\": true\n }\n ],\n \"pageSize\": 123,\n \"pageToken\": \"<string>\",\n \"key\": \"<string>\",\n \"includeArchived\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public.api.serval.com/v2/entities/search")
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 \"teamId\": \"<string>\",\n \"entityTypeId\": \"<string>\",\n \"entityTypeKey\": \"<string>\",\n \"filterGroups\": [\n {\n \"filters\": [\n {\n \"boolValue\": {\n \"eq\": true\n },\n \"fieldId\": \"<string>\",\n \"fieldKey\": \"<string>\"\n }\n ],\n \"sourceFilter\": {\n \"eq\": \"<string>\",\n \"ne\": \"<string>\"\n }\n }\n ],\n \"fieldSorts\": [\n {\n \"entitySource\": {},\n \"descending\": true\n }\n ],\n \"pageSize\": 123,\n \"pageToken\": \"<string>\",\n \"key\": \"<string>\",\n \"includeArchived\": true\n}"
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "<string>",
"key": "<string>",
"name": "<string>",
"teamId": "<string>",
"entityTypeId": "<string>",
"entityTypeKey": "<string>",
"createdByUserId": "<string>",
"updatedByUserId": "<string>",
"createdAt": "2025-01-15T01:30:15.000Z",
"updatedAt": "2025-01-15T01:30:15.000Z",
"deletedAt": "2025-01-15T01:30:15.000Z",
"archivedAt": "2025-01-15T01:30:15.000Z",
"fieldValues": [
{
"id": "<string>",
"entityId": "<string>",
"fieldId": "<string>",
"fieldKey": "<string>",
"fieldName": "<string>",
"dataType": "DATA_TYPE_UNSPECIFIED",
"value": 123,
"setByUserId": "<string>",
"setByAppInstanceId": "<string>",
"createdAt": "2025-01-15T01:30:15.000Z",
"deletedAt": "2025-01-15T01:30:15.000Z",
"pinned": true,
"redacted": true,
"sensitive": true,
"setByFormula": true
}
],
"sourceAppInstanceIds": [
"<string>"
],
"sharedMetadata": {
"sourceTeamId": "<string>",
"sourceTeamName": "<string>"
},
"sourceApps": [
{
"appInstanceId": "<string>",
"displayName": "<string>",
"serviceName": "<string>",
"serviceDisplayName": "<string>",
"logoUrl": "<string>",
"domain": "<string>",
"useIntegratedServiceRegistry": true,
"isCustom": true
}
]
}
],
"nextPageToken": "<string>"
}Authentication and permissions
Token requirements: User-based token (OAuth) or Organization-scoped API key or Team-scoped API key. Send a bearer access token for one of these identities. The permissions and resource restrictions below also apply.
| Credential | Access requirements |
|---|---|
| Organization-scoped API key | entities:read |
| Team-scoped API key | entities:read |
| User-based token (OAuth) | Supported, subject to permissions |
- Read records as a team: team_id is the team the caller acts as. Records of databases shared with that team (“Can read” or “Can write”) are returned from their owning teams; an entity type or schema the team cannot reach reads as not found (ListEntities, AggregateEntities) or matches nothing (SearchEntities). Schema and row-access rules still apply.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
The ID of the team the caller acts as.
Optional filter by entity type ID. A type outside the databases the team reaches (its own and those shared with it) matches nothing, whatever filters are set.
Optional filter by entity type key (alternative to entity_type_id). Resolved across the team's own databases and the databases shared with it; when a shared type has the same key as one of the team's own, the team's own type is used. Pass entity_type_id to address a shared type unambiguously.
Filter groups for complex filtering. OR between groups, AND within each group. Without an entity type, a field_key resolves across the team's own databases first, then the databases shared with it.
Show child attributes
Show child attributes
Sorting specifications. Field keys resolve as in filter_groups.
- EntitySort
- EntitySort
- EntitySort
Show child attributes
Show child attributes
Maximum number of results to return. Default is 2000, maximum is 5000.
Token for pagination. Leave empty for the first request.
Optional filter by entity key (exact match).
Include archived entities in the results. Default false (archived entities are hidden). Archived items keep their key reserved and can be unarchived; set this to discover them (e.g. to call UnarchiveEntity).
Was this page helpful?
curl --request POST \
--url https://public.api.serval.com/v2/entities/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"teamId": "<string>",
"entityTypeId": "<string>",
"entityTypeKey": "<string>",
"filterGroups": [
{
"filters": [
{
"boolValue": {
"eq": true
},
"fieldId": "<string>",
"fieldKey": "<string>"
}
],
"sourceFilter": {
"eq": "<string>",
"ne": "<string>"
}
}
],
"fieldSorts": [
{
"entitySource": {},
"descending": true
}
],
"pageSize": 123,
"pageToken": "<string>",
"key": "<string>",
"includeArchived": true
}
'import requests
url = "https://public.api.serval.com/v2/entities/search"
payload = {
"teamId": "<string>",
"entityTypeId": "<string>",
"entityTypeKey": "<string>",
"filterGroups": [
{
"filters": [
{
"boolValue": { "eq": True },
"fieldId": "<string>",
"fieldKey": "<string>"
}
],
"sourceFilter": {
"eq": "<string>",
"ne": "<string>"
}
}
],
"fieldSorts": [
{
"entitySource": {},
"descending": True
}
],
"pageSize": 123,
"pageToken": "<string>",
"key": "<string>",
"includeArchived": True
}
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({
teamId: '<string>',
entityTypeId: '<string>',
entityTypeKey: '<string>',
filterGroups: [
{
filters: [{boolValue: {eq: true}, fieldId: '<string>', fieldKey: '<string>'}],
sourceFilter: {eq: '<string>', ne: '<string>'}
}
],
fieldSorts: [{entitySource: {}, descending: true}],
pageSize: 123,
pageToken: '<string>',
key: '<string>',
includeArchived: true
})
};
fetch('https://public.api.serval.com/v2/entities/search', 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://public.api.serval.com/v2/entities/search",
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([
'teamId' => '<string>',
'entityTypeId' => '<string>',
'entityTypeKey' => '<string>',
'filterGroups' => [
[
'filters' => [
[
'boolValue' => [
'eq' => true
],
'fieldId' => '<string>',
'fieldKey' => '<string>'
]
],
'sourceFilter' => [
'eq' => '<string>',
'ne' => '<string>'
]
]
],
'fieldSorts' => [
[
'entitySource' => [
],
'descending' => true
]
],
'pageSize' => 123,
'pageToken' => '<string>',
'key' => '<string>',
'includeArchived' => true
]),
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://public.api.serval.com/v2/entities/search"
payload := strings.NewReader("{\n \"teamId\": \"<string>\",\n \"entityTypeId\": \"<string>\",\n \"entityTypeKey\": \"<string>\",\n \"filterGroups\": [\n {\n \"filters\": [\n {\n \"boolValue\": {\n \"eq\": true\n },\n \"fieldId\": \"<string>\",\n \"fieldKey\": \"<string>\"\n }\n ],\n \"sourceFilter\": {\n \"eq\": \"<string>\",\n \"ne\": \"<string>\"\n }\n }\n ],\n \"fieldSorts\": [\n {\n \"entitySource\": {},\n \"descending\": true\n }\n ],\n \"pageSize\": 123,\n \"pageToken\": \"<string>\",\n \"key\": \"<string>\",\n \"includeArchived\": true\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://public.api.serval.com/v2/entities/search")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"teamId\": \"<string>\",\n \"entityTypeId\": \"<string>\",\n \"entityTypeKey\": \"<string>\",\n \"filterGroups\": [\n {\n \"filters\": [\n {\n \"boolValue\": {\n \"eq\": true\n },\n \"fieldId\": \"<string>\",\n \"fieldKey\": \"<string>\"\n }\n ],\n \"sourceFilter\": {\n \"eq\": \"<string>\",\n \"ne\": \"<string>\"\n }\n }\n ],\n \"fieldSorts\": [\n {\n \"entitySource\": {},\n \"descending\": true\n }\n ],\n \"pageSize\": 123,\n \"pageToken\": \"<string>\",\n \"key\": \"<string>\",\n \"includeArchived\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://public.api.serval.com/v2/entities/search")
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 \"teamId\": \"<string>\",\n \"entityTypeId\": \"<string>\",\n \"entityTypeKey\": \"<string>\",\n \"filterGroups\": [\n {\n \"filters\": [\n {\n \"boolValue\": {\n \"eq\": true\n },\n \"fieldId\": \"<string>\",\n \"fieldKey\": \"<string>\"\n }\n ],\n \"sourceFilter\": {\n \"eq\": \"<string>\",\n \"ne\": \"<string>\"\n }\n }\n ],\n \"fieldSorts\": [\n {\n \"entitySource\": {},\n \"descending\": true\n }\n ],\n \"pageSize\": 123,\n \"pageToken\": \"<string>\",\n \"key\": \"<string>\",\n \"includeArchived\": true\n}"
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "<string>",
"key": "<string>",
"name": "<string>",
"teamId": "<string>",
"entityTypeId": "<string>",
"entityTypeKey": "<string>",
"createdByUserId": "<string>",
"updatedByUserId": "<string>",
"createdAt": "2025-01-15T01:30:15.000Z",
"updatedAt": "2025-01-15T01:30:15.000Z",
"deletedAt": "2025-01-15T01:30:15.000Z",
"archivedAt": "2025-01-15T01:30:15.000Z",
"fieldValues": [
{
"id": "<string>",
"entityId": "<string>",
"fieldId": "<string>",
"fieldKey": "<string>",
"fieldName": "<string>",
"dataType": "DATA_TYPE_UNSPECIFIED",
"value": 123,
"setByUserId": "<string>",
"setByAppInstanceId": "<string>",
"createdAt": "2025-01-15T01:30:15.000Z",
"deletedAt": "2025-01-15T01:30:15.000Z",
"pinned": true,
"redacted": true,
"sensitive": true,
"setByFormula": true
}
],
"sourceAppInstanceIds": [
"<string>"
],
"sharedMetadata": {
"sourceTeamId": "<string>",
"sourceTeamName": "<string>"
},
"sourceApps": [
{
"appInstanceId": "<string>",
"displayName": "<string>",
"serviceName": "<string>",
"serviceDisplayName": "<string>",
"logoUrl": "<string>",
"domain": "<string>",
"useIntegratedServiceRegistry": true,
"isCustom": true
}
]
}
],
"nextPageToken": "<string>"
}
