This guide explains how to fetch records from Caraer and how to build filter payloads that behave exactly as expected.
It is written for external developers integrating with the Records API.
- Which endpoint to use for record fetching
- What
mainObjectshould be - How filter payloads are structured
- How
showworks (including*) - How
sortworks - How
ANDandORlogic works in filter groups - How to filter on related records
- How to combine filters with search, sorting, and pagination
Use:
POST /api/v2/records/index
With optional query params:
parse=true|falsearchived=true|falserelatedRecordUuid=RECORD_UUID
Basic example:
curl -X POST "https://your-company.caraer.com/api/v2/records/index?parse=true" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"limit": 25,
"mainObject": "candidate"
}'mainObject is required context for record fetching.
Use the object name of the record type you want to list, for example:
candidatevacancycontact
Example:
{
"mainObject": "candidate",
"page": 1,
"limit": 25
}Why it matters:
- It defines which node type is the base of the query.
- It controls how
filter,show, andsortare resolved. - It is also used for permission checks on property access.
If mainObject does not match a valid object name in your environment, request building and/or query execution will fail.
Filtering is sent inside the request body as filter.
High-level shape:
{
"page": 1,
"limit": 25,
"mainObject": "candidate",
"query": null,
"filter": {
"groups": [
{
"items": [
{
"object": null,
"relation": null,
"property": "status_candidate",
"operator": "equals_exactly",
"value": "new"
}
]
}
]
}
}object: object context used by the filter itemrelation: relation name if the filter traverses a relation (*is allowed for any relation in relation-existence checks)property: property name to filter on; if omitted, item becomes a relation existence checkoperator: filter operator namevalue: value used by the operatorrelationIncluded(optional, defaulttrue): for relation existence checks (property=null), controls include/exclude relation matches
Important behavior:
- If you are filtering properties on the
mainObject, you usually leaveobjectasnull. - If you set
objectto the same value asmainObject, the filter is treated as filtering through a related node of that same object (self-related records), not as a plain main-object property shortcut. - If
objectis set andrelationisnull, filtering targets related records of that object type regardless of relation name. - If
objectis set andrelationis also set, filtering targets related records through that specific relation only.
Practical recommendation: for normal mainObject property filtering, keep object and relation as null in filter items.
show controls which fields are returned for each record.
Basic shape:
{
"show": [
{ "object": "candidate", "relation": null, "property": "firstname" },
{ "object": "candidate", "relation": null, "property": "email" }
]
}You can request all readable properties of the main object with:
{
"show": [{ "object": "candidate", "relation": null, "property": "*" }]
}Important behavior:
*expansion is applied for the main object wildcard pattern.- Backend resolves it to all readable properties for that main object.
- Access rules still apply: only properties the caller can read are returned.
If you need a stable API response contract, explicitly list the properties instead of relying on *.
sort controls ordering of result rows.
Basic shape:
{
"sort": [
{
"object": "candidate",
"relation": null,
"property": "updatedAt",
"direction": "DESC"
}
]
}Rules:
directionsupportsASCandDESC.- You can provide multiple sort items to create secondary/tertiary ordering.
- Use properties that exist and are readable in the requested context.
Example with fallback ordering:
{
"sort": [
{
"object": "candidate",
"relation": null,
"property": "status_candidate",
"direction": "ASC"
},
{
"object": "candidate",
"relation": null,
"property": "updatedAt",
"direction": "DESC"
}
]
}Filter logic is:
- Items inside one group are combined with
AND - Groups inside one filter are combined with
OR
So groups let you create (A AND B) OR (C AND D) patterns.
Example with two groups:
{
"filter": {
"groups": [
{
"items": [
{
"property": "status_candidate",
"operator": "equals_exactly",
"value": "new"
},
{
"property": "source",
"operator": "equals_exactly",
"value": "linkedin"
}
]
},
{
"items": [
{
"property": "status_candidate",
"operator": "equals_exactly",
"value": "in_progress"
},
{
"property": "source",
"operator": "equals_exactly",
"value": "referral"
}
]
}
]
}
}This means:
(status=new AND source=linkedin) OR (status=in_progress AND source=referral)
| Operator | Typical meaning |
|---|---|
equals_exactly | Exact equality |
equals_flexibly | Case-insensitive equality |
not_equals_exactly | Exact inequality |
not_equals_flexibly | Case-insensitive inequality |
bigger_than | Greater than |
smaller_than | Less than |
bigger_than_or_equal_to | Greater than or equal |
smaller_than_or_equal_to | Less than or equal |
contains_exactly | Contains (case-sensitive) |
contains_flexibly | Contains (case-insensitive) |
not_contains_exactly | Does not contain (case-sensitive) |
not_contains_flexibly | Does not contain (case-insensitive) |
starts_with_exactly | Starts with (case-sensitive) |
starts_with_flexibly | Starts with (case-insensitive) |
ends_with_exactly | Ends with (case-sensitive) |
ends_with_flexibly | Ends with (case-insensitive) |
is_null | Empty / null |
is_not_null | Not empty / not null |
any | Any of provided values |
all_flexibly | Contains all provided values |
all_exactly | Matches all provided values exactly |
distance_between | Distance-based comparison |
range | In between min/max |
In default Caraer property configuration, operator availability is primarily driven by property type, and formats of that type follow the same list.
| Property type | Formats | Supported operators |
|---|---|---|
string | email, multi-line, phone, single-line, url | is_null, is_not_null, equals_exactly, not_equals_exactly, contains_flexibly, not_contains_flexibly, starts_with_flexibly, ends_with_flexibly |
number | number, currency | is_null, is_not_null, equals_exactly, not_equals_exactly, bigger_than, smaller_than, bigger_than_or_equal_to, smaller_than_or_equal_to, range |
date | date | is_null, is_not_null, equals_exactly, not_equals_exactly, bigger_than, smaller_than, bigger_than_or_equal_to, smaller_than_or_equal_to, range |
checkbox | single-checkbox | is_null, is_not_null, equals_exactly, not_equals_exactly |
single-select | single-select | any, is_null, is_not_null |
multi-select | multi-select | any, all_flexibly, all_exactly, is_null, is_not_null |
tag | tag | is_null, is_not_null, equals_exactly, not_equals_exactly, any, all_flexibly, all_exactly |
range | number-range, currency-range | range |
structure | structure | contains_flexibly, is_null, is_not_null |
file | file | is_null, is_not_null |
linked-property | linked-property | Based on the property it's linked to |
When property is null, filter items behave as relation existence checks (relationIncluded=true/false). In that case, property-type operator tables do not apply because the filter is relation-based, not property-value-based.
You can filter by relation presence even without specifying a property.
Relation existence example (candidate has any relation to vacancy):
{
"filter": {
"groups": [
{
"items": [
{
"object": "vacancy",
"relation": "*",
"property": null,
"relationIncluded": true
}
]
}
]
}
}Relation non-existence example (candidate has no applied_for relation to vacancy):
{
"filter": {
"groups": [
{
"items": [
{
"object": "vacancy",
"relation": "applied_for",
"property": null,
"relationIncluded": false
}
]
}
]
}
}When you pass relatedRecordUuid as a query parameter, Caraer can help shape relation-aware filtering:
- If no filter is provided, it defaults to records related to that record
- If filter values contain smarten placeholders, they are resolved against that related record context
Example:
curl -X POST "https://your-company.caraer.com/api/v2/records/index?relatedRecordUuid=RELATED_UUID" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"limit": 20,
"mainObject": "candidate",
"filter": { "groups": [] }
}'You can combine all of these in one request:
{
"page": 1,
"limit": 20,
"mainObject": "candidate",
"query": "jane",
"filter": {
"groups": [
{
"items": [
{
"property": "status_candidate",
"operator": "equals_exactly",
"value": "in_progress"
}
]
}
]
},
"sort": [
{
"object": "candidate",
"relation": null,
"property": "updatedAt",
"direction": "DESC"
}
]
}- Always set
mainObjectto the object you are fetching. - Keep
mainObjectaligned with the object name used inshow/sortwhere possible. - Use exact property names from your Caraer schema.
- Start with one simple group, then add complexity.
- Validate operator spelling (
equals_exactly, notEQUALS). - Use explicit
showfields for stable integrations; use*mainly for exploration. - Use
parse=trueonly if you need human-readable values in response.