Advanced Filtering
The Content API provides a powerful where parameter to filter, sort, and retrieve the exact content entries you need. You can create complex queries by combining multiple conditions on both core system fields and your own custom fields.
Operators
The following operators can be used within where clauses to filter your content.
| Operator | Description | Example (where[price][operator]=value) |
|---|---|---|
| Equals: Matches values that are equal without using eq param. | where[price]=100 | |
eq | Equals: Matches values that are equal. | where[price][eq]=100 |
not | Not Equals: Matches values that are not equal. | where[price][not]=100 |
gt | Greater Than: Matches values greater than the specified value. | where[price][gt]=100 |
gte | Greater Than or Equals: Matches values greater than or equal. | where[price][gte]=100 |
lt | Less Than: Matches values less than the specified value. | where[price][lt]=100 |
lte | Less Than or Equals: Matches values less than or equal. | where[price][lte]=100 |
like | Like: Simple LIKE search (case-insensitive). | where[name][like]=shirt |
in | In: Matches any value in a comma-separated list or array. | where[id][in]=1,2,3 |
not_in | Not In: Matches any value not in a comma-separated list. | where[id][not_in]=1,2,3 |
between | Between: Matches values between two comma-separated values. | where[price][between]=50,150 |
not_between | Not Between: Matches values outside two comma-separated values. | where[price][not_between]=50,150 |
null | Is Null: Matches entries where the field value is null. | where[description][null]=true |
not_null | Is Not Null: Matches entries where the field value is not null. | where[description][not_null]=true |
Example Data
To demonstrate filtering, let's assume we have a products collection with the following fields:
name(text)price(number)in_stock(boolean)tags(text, repeatable)category(relation to acategoriescollection)
The categories collection has a name field (e.g., "Apparel", "Footwear").
Filtering by Field
Simple Equality
This is the default operator. It finds products where the name is exactly "Classic T-Shirt".
/products?where[name]=Classic T-ShirtUsing Other Operators
Finds products where the price is greater than or equal to 100.
/products?where[price][gte]=100Filtering by Boolean
Finds products that are in stock.
/products?where[in_stock]=trueFiltering by Array Content (Tags)
Finds products that have the tag "sale".
/products?where[tags]=saleCombining Filters
AND Logic (Default)
You can combine filters by adding multiple where parameters. This finds products that are in stock AND have a price less than 50.
/products?where[in_stock]=true&where[price][lt]=50OR Logic
To use OR logic, group your conditions under where[or]. This finds products where the name contains "shirt" OR "jacket".
/products?where[or][0][name][like]=shirt&where[or][1][name][like]=jacketRelational Filtering
You can filter entries based on the fields of a related entry. This query finds products where the related category's name is "Apparel".
/products?where[category][name]=ApparelYou can even combine this with other operators. This finds products where the category name is not "Footwear".
/products?where[category][name][not]=FootwearFull Code Examples
Here is how you would build a more complex query using various clients. This query looks for products in the "Apparel" category that cost between 50 and 150.
import { createClient } from '@elmapicms/js-sdk';
const client = createClient(
'https://your-domain.com/api',
'YOUR_API_TOKEN',
'YOUR_PROJECT_UUID'
);
// Get products in the "Apparel" category that cost between 50 and 150
const products = await client.getEntries('products', {
where: {
category: { name: 'Apparel' },
price: { between: '50,150' }
}
});axios.get('https://your-domain.com/api/products', {
params: {
'where[category][name]': 'Apparel',
'where[price][between]': '50,150'
},
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN', // Required for private APIs
'project-id': 'YOUR_PROJECT_UUID'
}
});use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'Accept' => 'application/json',
'Authorization' => 'Bearer YOUR_API_TOKEN',
'project-id' => 'YOUR_PROJECT_UUID'
])->get("https://your-domain.com/api/products", [
'where[category][name]' => 'Apparel',
'where[price][between]' => '50,150'
]);import React, { useEffect } from 'react';
function FilteredProducts() {
useEffect(() => {
const fetchFilteredProducts = async () => {
try {
const params = new URLSearchParams({
'where[category][name]': 'Apparel',
'where[price][between]': '50,150'
});
const response = await fetch(`https://your-domain.com/api/products?${params}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN', // Required for private APIs
'project-id': 'YOUR_PROJECT_UUID'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Handle data...
} catch (error) {
console.error('Error fetching products:', error);
}
};
fetchFilteredProducts();
}, []);
return <div>...</div>;
}<script setup>
import { onMounted } from 'vue';
onMounted(async () => {
try {
const params = new URLSearchParams({
'where[category][name]': 'Apparel',
'where[price][between]': '50,150'
});
const response = await fetch(`https://your-domain.com/api/products?${params}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_API_TOKEN', // Required for private APIs
'project-id': 'YOUR_PROJECT_UUID'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Handle data...
} catch (error) {
console.error('Error fetching products:', error);
}
});
</script>curl -G "https://your-domain.com/api/products" \
-d "where[category][name]=Apparel" \
-d "where[price][between]=50,150" \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "project-id: YOUR_PROJECT_UUID"