Skip to main content

Query Parameters

The Tribe CRM API uses OData (Open Data Protocol) for querying, giving you powerful and flexible capabilities to precisely control what data you retrieve and how it's formatted.

Selecting Fields ($select)

By default, the API returns all fields for a requested entity. Use $select to return only the fields you need.

GET /v1/odata/Relation_Person?$select=FirstName,LastName
tip

The ID field is always returned, even if not explicitly selected.

Combine $expand with $select to pick specific fields from related entities:

GET /v1/odata/Activity_SalesOpportunity?$expand=SalesRepresentative($select=Name)

Selecting Custom Fields

Custom fields use their API name, which differs from the display name in the UI. To find it:

  1. Go to Configuration in Tribe CRM (Relations, Activity, or Own entities page)
  2. Click on the entity, then navigate to the Fields tab
  3. Copy the API name (the value in grey under the display name)

In endpoints, replace hyphens (-) with double underscores (__) and prefix with _:

GET /v1/odata/Activity_SalesOpportunity?$select=_117ecf60__d492__48a1__8aab__a131ad465fd5

Filtering ($filter)

The $filter parameter narrows down results. Filters can be applied to all value types.

Comparison Operators

OperatorDescriptionExample
eqEqual$filter=Number eq 1601
neNot equal$filter=IsClosed ne true
gtGreater than$filter=Amount gt 10000
geGreater than or equal$filter=Amount ge 5000
ltLess than$filter=Amount lt 1000
leLess than or equal$filter=Amount le 500
inNot supported
hasNot supported

Logical Operators

OperatorDescriptionExample
andLogical AND$filter=(FirstName eq 'Jan') and (LastName eq 'Jansen')
orLogical OR$filter=Number gt 100 or _Name eq 'INV-9001'
notLogical NOT$filter=not endswith(_Name, 'test')

String Functions

All string functions are case insensitive.

FunctionDescriptionExample
containsContains substring$filter=contains(Name, 'pet')
startswithStarts with$filter=startswith(Name, 'pet')
endswithEnds with$filter=endswith(Name, 'pet')

Filtering by Type (_Type)

:::warning Limitation — _Type cannot be filtered The _Type property is returned in every response so you can see which type a record actually is, but $filter clauses on _Type are silently ignored by the API. This applies on every entity set — base Entity, intermediate sets like Activity and Relation, and every subtype set.

# All of these IGNORE the _Type clause and return unrelated rows:
GET /v1/odata/Entity?$filter=_Type eq 'Relation.Person'
GET /v1/odata/Entity?$filter=startswith(_Type, 'Activity')
GET /v1/odata/Activity?$filter=_Type eq 'Activity.Invoice'
GET /v1/odata/Relation?$filter=_Type eq 'Relation.Person'

The server accepts the query (200 OK) but the _Type predicate is dropped before evaluation, so you get the unfiltered set's first rows — easy to mistake for "matching" results.

What to do instead — query the type-specific entity set directly. Each subtype is exposed as its own collection that returns that subtype and all its descendants automatically.

# Just the type you want (and its subtypes):
GET /v1/odata/Relation_Person # all persons
GET /v1/odata/Activity_Invoice # all invoices
GET /v1/odata/Relationship_Person_Contact_Standard # all standard contacts

# Combine with other filters that ARE supported:
GET /v1/odata/Relation_Person?$filter=contains(_Name,'jansen')
GET /v1/odata/Activity_Invoice?$filter=CreationDate gt 2025-01-01T00:00:00Z

To search across multiple types in one request, fire one query per type-specific set in parallel and merge the results client-side. :::

Filtering on Dates

Date format: YYYY-MM-DD. DateTime format: YYYY-MM-DDTHH:MM:SSZ (UTC).

# Exact date
$filter=BirthDate eq 2021-05-17

# Date range
$filter=CreationDate gt 2021-05-17T12:43:48Z and CreationDate lt 2021-05-22T11:43:48Z

Filtering on Booleans

$filter=IsRoot eq true
$filter=IsClosed eq false

Filtering on Linked Entities

Filter on a field from a related entity using path notation:

$filter=Phase/Code eq 'Concept'

Filtering on Null Values

$filter=DebtorNumber ne null
$filter=DiscountPercentage eq null

Escaping Single Quotes

If the search value contains a single quote ('), escape it with an extra ':

$filter=Name eq 'Peter''s test'

Ordering ($orderby)

Sort results in ascending (asc) or descending (desc) order.

GET /v1/odata/Relation_Person?$orderby=LastName desc
GET /v1/odata/ProductLine?$orderby=SortIndex asc

Expanding Relations ($expand)

By default, API responses include only the fields of the requested entity. Use $expand to include related entities in the response.

GET /v1/odata/Relation_Person?$expand=Addresses,Gender
GET /v1/odata/Activity_Offer?$expand=Relationship,Contact,ProductLines,Phase

Pagination ($top & $skip)

An API call returns a maximum of 100 records. To retrieve more, use pagination.

ParameterDescription
$topMaximum number of records to return (max 100)
$skipNumber of records to skip before selecting
$orderbyRequired when using pagination — ensures consistent ordering across pages
note

When using $top and $skip, always include $orderby to guarantee consistent results across pages. A best practice is to use ID as the $orderby field.

GET /v1/odata/Relation_Person?$top=10&$skip=0&$orderby=ID # Page 1 (records 1-10)
GET /v1/odata/Relation_Person?$top=10&$skip=10&$orderby=ID # Page 2 (records 11-20)
GET /v1/odata/Relation_Person?$top=10&$skip=20&$orderby=ID # Page 3 (records 21-30)

Counting ($count)

Include the total number of matching records in the response using $count=true. This can be combined with $filter.

GET /v1/odata/Relation_Person?$count=true

Response:

{
"@odata.count": 121,
"value": [...]
}

Combining Parameters

All query parameters can be combined in a single request:

GET /v1/odata/Activity_SalesOpportunity?$filter=Amount gt 5000&$select=Subject,Amount,Probability&$expand=Phase&$orderby=CreationDate desc&$top=10&$count=true

Reference Deletes ($ref)

Some delete operations target a reference — a link to another entity — rather than the entity itself. The OData $ref suffix on the URL signals "delete the link, not the target." Both forms return 204 No Content on success and never delete the referenced entity.

Clearing a single-reference field (1:1)

Datastore-backed fields like Source, Gender, Branch, Language hold one optional reference. To empty the field without overwriting it with another value, send a DELETE to the field's $ref path:

DELETE /v1/odata/Activity_SalesOpportunity({id})/Source/$ref

After the call, the field reads as null. The Datastore entry it pointed at is untouched. See Activity for an in-context example.

Removing one item from a many-to-many list (N:N)

Collection-valued navigation properties like Labels, Tags, or any link table show up in responses as an array. To remove a single entry without rebuilding the array, send a DELETE whose path includes both the parent ID and the specific target ID, then $ref:

DELETE /v1/odata/Activity_SalesOpportunity({id})/Labels({labelId})/$ref

Only the link between the two records is removed — the Label itself remains and can be re-attached or used on other activities.