Skip to content

Filtering

Query filter syntax and operators


Filtering allows clients to request a subset of resources matching specific criteria. Filters are applied server-side before returning results.


A filter specifies a single condition:

{
"attribute": "status",
"operator": "equals",
"value": "pending"
}
FieldTypeRequiredDescription
attributestringYesAttribute to filter on
operatorstringYesComparison operator
valueanyConditionalValue to compare (type depends on operator)
booleanstringNoBoolean combinator (and, or)

OperatorSQL EquivalentValue TypeDescription
equals=anyExact match
not_equals!=anyNot equal
{ "attribute": "status", "operator": "equals", "value": "active" }
{ "attribute": "type", "operator": "not_equals", "value": "draft" }
OperatorSQL EquivalentValue TypeDescription
greater_than>number/stringGreater than
greater_than_or_equal_to>=number/stringGreater than or equal
less_than<number/stringLess than
less_than_or_equal_to<=number/stringLess than or equal
{ "attribute": "amount", "operator": "greater_than", "value": 100 }
{ "attribute": "created_at", "operator": "greater_than_or_equal_to", "value": "2024-01-01T00:00:00Z" }
OperatorSQL EquivalentValue TypeDescription
likeLIKEstringPattern match (use % wildcard)
not_likeNOT LIKEstringNegative pattern match
{ "attribute": "email", "operator": "like", "value": "%@example.com" }
{ "attribute": "name", "operator": "like", "value": "John%" }
{ "attribute": "code", "operator": "not_like", "value": "TEST%" }
OperatorSQL EquivalentValue TypeDescription
inINarrayValue in set
not_inNOT INarrayValue not in set
{ "attribute": "status", "operator": "in", "value": ["pending", "processing", "shipped"] }
{ "attribute": "country_code", "operator": "not_in", "value": ["US", "CA"] }
OperatorSQL EquivalentValue TypeDescription
betweenBETWEENarray[2]Value in range (inclusive)
not_betweenNOT BETWEENarray[2]Value outside range
{ "attribute": "price", "operator": "between", "value": [10, 100] }
{ "attribute": "created_at", "operator": "between", "value": ["2024-01-01", "2024-01-31"] }
OperatorSQL EquivalentValue TypeDescription
is_nullIS NULLAttribute is null
is_not_nullIS NOT NULLAttribute is not null
{ "attribute": "deleted_at", "operator": "is_null" }
{ "attribute": "verified_at", "operator": "is_not_null" }

Note: value is not required for null operators.


Filters are organized by resource using an object:

{
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "active" },
{ "attribute": "created_at", "operator": "greater_than", "value": "2024-01-01T00:00:00Z" }
]
}
}

The self key targets the primary resource. Additional keys target relationships.

Without explicit boolean, filters are combined with AND:

{
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "active" },
{ "attribute": "type", "operator": "equals", "value": "premium" }
]
}
}
// SQL: WHERE status = 'active' AND type = 'premium'

Explicit AND (same as default):

{
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "active", "boolean": "and" },
{ "attribute": "verified", "operator": "equals", "value": true, "boolean": "and" }
]
}
}
// SQL: WHERE status = 'active' AND verified = true
{
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "pending", "boolean": "or" },
{ "attribute": "status", "operator": "equals", "value": "processing", "boolean": "or" }
]
}
}
// SQL: WHERE status = 'pending' OR status = 'processing'

Note: For simple OR on same attribute, prefer in operator:

{ "attribute": "status", "operator": "in", "value": ["pending", "processing"] }

Filters are applied sequentially, with each filter’s boolean determining how it connects to the previous condition:

{
"filters": {
"self": [
{ "attribute": "type", "operator": "equals", "value": "order" },
{ "attribute": "status", "operator": "equals", "value": "pending", "boolean": "or" },
{ "attribute": "status", "operator": "equals", "value": "failed", "boolean": "or" }
]
}
}
// SQL: WHERE type = 'order' OR status = 'pending' OR status = 'failed'

Important: Boolean operators connect filters left-to-right without automatic grouping. For complex grouping logic, use the in operator:

{
"filters": {
"self": [
{ "attribute": "type", "operator": "equals", "value": "order" },
{ "attribute": "status", "operator": "in", "value": ["pending", "failed"] }
]
}
}
// SQL: WHERE type = 'order' AND status IN ('pending', 'failed')

Filters can target different resources in a query:

{
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "active" }
],
"customer": [
{ "attribute": "country_code", "operator": "equals", "value": "FI" }
]
}
}
KeyDescription
selfFilters on the primary resource
<relationship>Filters on related resources

Filtering by relationship creates a WHERE EXISTS condition:

{
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "pending" }
],
"customer": [
{ "attribute": "type", "operator": "equals", "value": "vip" }
]
}
}
// SQL: WHERE status = 'pending'
// AND EXISTS (SELECT 1 FROM customers WHERE customers.id = orders.customer_id AND type = 'vip')

Servers MUST define which attributes are filterable per resource:

{
"filters": {
"self": ["id", "status", "created_at", "total_amount"],
"customer": ["id", "type", "country_code"]
}
}
  • Filtering on non-allowed attributes MUST return an error
  • Servers SHOULD expose allowed filters via mesh.describe
{
"errors": [{
"code": "INVALID_ARGUMENTS",
"message": "Filter attribute not allowed: secret_field",
"retryable": false,
"source": {
"pointer": "/call/arguments/filters/self/0/attribute"
},
"details": {
"attribute": "secret_field",
"allowed": ["id", "status", "created_at", "total_amount"]
}
}]
}

Most operators accept string values:

{ "attribute": "status", "operator": "equals", "value": "pending" }

Comparison operators work with numbers:

{ "attribute": "quantity", "operator": "greater_than", "value": 10 }
{ "attribute": "price", "operator": "between", "value": [10.00, 99.99] }
{ "attribute": "is_active", "operator": "equals", "value": true }
{ "attribute": "verified", "operator": "equals", "value": false }

Use ISO 8601 format:

{ "attribute": "created_at", "operator": "greater_than", "value": "2024-01-15T10:30:00Z" }
{ "attribute": "date", "operator": "between", "value": ["2024-01-01", "2024-12-31"] }

Use null operators, not equals with null:

// Correct
{ "attribute": "deleted_at", "operator": "is_null" }
// Incorrect
{ "attribute": "deleted_at", "operator": "equals", "value": null }

{
"call": {
"function": "orders.list",
"version": "1",
"arguments": {
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "pending" }
]
}
}
}
}
{
"arguments": {
"filters": {
"self": [
{ "attribute": "status", "operator": "in", "value": ["pending", "processing"] },
{ "attribute": "created_at", "operator": "greater_than_or_equal_to", "value": "2024-01-01T00:00:00Z" },
{ "attribute": "total_amount", "operator": "greater_than", "value": 50 }
]
}
}
}
{
"arguments": {
"filters": {
"self": [
{ "attribute": "tracking_number", "operator": "equals", "value": "MH726955185FI", "boolean": "or" },
{ "attribute": "parcel_tracking_number", "operator": "equals", "value": "MH726955185FI", "boolean": "or" },
{ "attribute": "return_tracking_number", "operator": "equals", "value": "MH726955185FI", "boolean": "or" }
]
}
}
}
{
"arguments": {
"filters": {
"self": [
{ "attribute": "email", "operator": "like", "value": "%@company.com" },
{ "attribute": "name", "operator": "not_like", "value": "Test%" }
]
}
}
}
{
"arguments": {
"filters": {
"self": [
{ "attribute": "created_at", "operator": "between", "value": ["2024-01-01T00:00:00Z", "2024-01-31T23:59:59Z"] }
]
}
}
}
{
"arguments": {
"filters": {
"self": [
{ "attribute": "deleted_at", "operator": "is_null" },
{ "attribute": "verified_at", "operator": "is_not_null" }
]
}
}
}
{
"arguments": {
"filters": {
"self": [
{ "attribute": "status", "operator": "equals", "value": "active" }
],
"vendor": [
{ "attribute": "type", "operator": "in", "value": ["premium", "enterprise"] }
],
"location": [
{ "attribute": "country_code", "operator": "equals", "value": "FI" }
]
},
"relationships": ["vendor", "location"]
}
}
{
"protocol": { "name": "mesh", "version": "0.1.0" },
"id": "req_complex",
"call": {
"function": "tracking_events.list",
"version": "1",
"arguments": {
"fields": {
"self": ["id", "status", "location", "occurred_at"],
"shipment": ["id", "tracking_number"]
},
"filters": {
"self": [
{ "attribute": "occurred_at", "operator": "greater_than", "value": "2024-01-01T00:00:00Z" },
{ "attribute": "status", "operator": "in", "value": ["in_transit", "delivered"] }
],
"shipment": [
{ "attribute": "carrier", "operator": "equals", "value": "posti" }
]
},
"sorts": [
{ "attribute": "occurred_at", "direction": "desc" }
],
"relationships": ["shipment"],
"pagination": {
"limit": 50
}
}
}
}