Strapi API Parameters — Populate, Fields, Sort, Filters, Locale, and PublicationState
In this tutorial, you will master Strapi's API query parameters — the tools that let you control exactly what data the API returns, including which relations to include, which fields to select, how to sort and filter, and how to handle localization and publication state.
What You'll Learn
- How to use the
populateparameter at multiple depth levels - How to select specific fields with the
fieldsparameter - How to combine multiple parameters in a single request
- How the
localeparameter works with content translation - How
publicationStatecontrols draft/preview access - How to construct complex query URLs with multiple parameters
Why It Matters
The difference between a slow, bloated API and a fast, focused one is how well you use query parameters. Fetching all fields and all relations for a list page that only needs titles and IDs wastes bandwidth and processing time. Mastering API parameters lets you write frontend code that is fast, efficient, and cost-effective.
Real-World Use
A mobile app displays a list of 20 products. Each item only needs the product name, price, and thumbnail image. Using fields to request only name and price, and populate to include only the thumbnail image, reduces the API response from 50KB to 2KB per page. On a mobile network, this means 400ms load times instead of 3 seconds.
Learning Path
flowchart LR A["REST API"] --> B["API Parameters
-- You are here"]:::current B --> C["GraphQL Setup"] C --> D["API Customization"] D --> E["API Security"] classDef current fill:#4945ff,color:#fff,stroke-width:2px
The Populate Parameter
The populate parameter includes related data in the API response. Without it, relations return empty objects.
// No population — relations are empty
// GET /api/articles
// Response:
{
"data": [{
"attributes": {
"title": "Article 1",
"author": { "data": null } // Empty without populate
}
}]
}
// Single relation
// GET /api/articles?populate=author
// Response includes author data
// Multiple relations
// GET /api/articles?populate=author,tags,category
Deep population uses bracket syntax:
// Two levels deep
// GET /api/articles?populate[author][populate]=avatar
// Three levels deep
// GET /api/articles?populate[author][populate][articles][populate]=tags
// Mix deep and shallow
// GET /api/articles?populate[author]=avatar&populate=tags
Strapi limits population depth to prevent infinite loops with circular relations. The default max depth is 5 levels.
The Fields Parameter
The fields parameter selects specific attributes to return. The id is always included.
// Select only title and createdAt
// GET /api/articles?fields[0]=title&fields[1]=createdAt
// Response:
{
"data": [{
"id": 1,
"attributes": {
"title": "Article 1",
"createdAt": "2026-06-28T..."
}
}]
}
You can use fields together with populate:
// Select fields on the main type and populated relations
// GET /api/articles?fields[0]=title&populate[author][fields][0]=name
// Returns articles with only title, and author with only name
The Sort Parameter
Sort controls the order of returned entries.
// Single field ascending
// GET /api/articles?sort=title
// Single field descending
// GET /api/articles?sort=title:desc
// Multiple fields (array syntax)
// GET /api/articles?sort[0]=createdAt:desc&sort[1]=title:asc
// Sort by nested relation fields
// GET /api/articles?populate=author&sort=author.name:asc
When sorting by multiple fields, entries with equal values in the first sort field are ordered by the second sort field.
The Filters Parameter
Filters query content based on conditions. The syntax uses operators like $eq, $ne, $gt, $lt, $in, $containsi, etc.
// Equality
// GET /api/articles?filters[title]=ExactMatch
// GET /api/articles?filters[title][$eq]=ExactMatch
// Greater than / less than
// GET /api/articles?filters[views][$gte]=100
// GET /api/articles?filters[price][$lt]=50.00
// String matching
// GET /api/articles?filters[title][$containsi]=strapi
// GET /api/articles?filters[title][$startsWith]=How
// Array membership
// GET /api/articles?filters[id][$in]=1,3,5
// GET /api/articles?filters[status][$notIn]=draft,archived
// Null checks
// GET /api/articles?filters[author][$null]=true
// GET /api/articles?filters[author][$notNull]=true
// Date range
// GET /api/articles?filters[createdAt][$gte]=2026-01-01&filters[createdAt][$lte]=2026-06-30
Combine filters for AND logic:
// AND: title contains "guide" AND views >= 100
// GET /api/articles?filters[title][$containsi]=guide&filters[views][$gte]=100
Use $or for OR logic:
// OR: title contains "guide" OR title contains "tutorial"
// GET /api/articles?filters[$or][0][title][$containsi]=guide&filters[$or][1][title][$containsi]=tutorial
Filter on relation fields:
// Filter by author name
// GET /api/articles?filters[author][name][$eq]=Alice
// Filter by category slug
// GET /api/articles?filters[category][slug][$eq]=javascript
The Locale Parameter
When the i18n plugin is enabled, the locale parameter controls which language version of the content to return.
// Get content in English
// GET /api/articles?locale=en
// Get content in French
// GET /api/articles?locale=fr
// Get all localizations of an entry
// GET /api/articles?locale=all
// Returns entries in all available locales
// Get content in the default locale
// GET /api/articles?locale=en (where en is the default)
// If locale is omitted, the default locale is used
When using locale, Strapi returns the content for the requested locale. If the content does not exist in that locale, Strapi's behavior depends on the i18n configuration. By default, it falls back to the default locale.
The PublicationState Parameter
The publicationState parameter controls whether draft entries are included.
// Published only (default)
// GET /api/articles?publicationState=live
// Preview (includes drafts, requires auth)
// GET /api/articles?publicationState=preview
// All entries (includes drafts and published, requires auth)
// GET /api/articles?publicationState=all
Without authentication, preview and all return the same as live. You need a valid JWT or API token with appropriate permissions to see draft content.
Combining Multiple Parameters
The real power comes from combining parameters:
// Full-featured query
GET /api/articles?
populate[author][fields][0]=name&
populate[author][fields][1]=avatar&
populate=tags&
fields[0]=title&
fields[1]=content&
sort[0]=createdAt:desc&
pagination[page]=1&
pagination[pageSize]=10&
filters[category][slug][$eq]=javascript&
filters[author][name][$containsi]=alice&
locale=en&
publicationState=live
// This query:
// - Returns articles in English
// - Only published articles
// - From the JavaScript category
// - By authors with "alice" in their name
// - Sorted by newest first
// - Page 1, 10 per page
// - With only title and content fields
// - Including author name/avatar and tags
URL Encoding
When building URLs programmatically, remember to encode special characters:
// JavaScript: Use URLSearchParams or encodeURIComponent
const params = new URLSearchParams({
"populate[author][fields][0]": "name",
"fields[0]": "title",
"sort": "createdAt:desc"
});
const url = `http://localhost:1337/api/articles?${params.toString()}`;
// The encoded URL:
// http://localhost:1337/api/articles?populate%5Bauthor%5D%5Bfields%5D%5B0%5D=name&fields%5B0%5D=title&sort=createdAt%3Adesc
Different HTTP clients handle URL encoding differently. Ensure your client properly encodes square brackets and special characters.
Common Mistakes
Not using fields and over-fetching. Frontend list views often only need a few fields. Without
fields, the API returns all attributes including large richtext and JSON fields. Always specify fields for list endpoints.Using populate wildcard in production.
?populate=*loads every relation at every level. On a content type with 5 relations, each with their own relations, this can return thousands of fields. Always specify exact relations.Building URLs manually with string concatenation. String concatenation for query parameters leads to encoding bugs and malformed URLs. Use URL-building libraries or URLSearchParams.
Forgetting locale for multilingual sites. Without the
localeparameter, Strapi returns the default locale. Users of other locales see wrong language content.Not using filters for pagination efficiency. Fetching all entries and filtering on the frontend is inefficient for large datasets. Always use server-side filters, pagination, and sorting.
Practice Questions
Write a query that returns only the names and emails of users who registered in the last 30 days. Answer:
GET /api/users?fields[0]=name&fields[1]=email&filters[createdAt][$gte]=2026-05-28How do you populate a nested relation two levels deep? Answer:
GET /api/articles?populate[author][populate]=profileor using bracket notation?populate[author][populate][0]=profile.What happens when you use
publicationState=previewwithout authentication? Answer: It returns the same aspublicationState=live(published entries only). Authentication is required to see drafts.Challenge: Write a JavaScript async function that builds and executes a complex Strapi API query. The function should take parameters for content type name, fields, populate, filters, sort, pagination, locale, and publication state, build the URL safely using URLSearchParams, execute the fetch, and return the parsed data. Include error handling for network errors and API error responses.
FAQ
Mini Project
Your task: Create a parameter-optimized API integration.
- Create at least 20 articles across 3 categories with 5 different authors and various tags.
- Build the following API queries and compare the response sizes:
- Full response without parameters
- Response with only title and author name fields
- Response with pagination (5 per page)
- Response filtered to a specific category
- Response sorted by views descending
- Measure the response size of each query using curl with
-w "%{size_download}". - Document the size difference between the most and least efficient query.
What's Next
Now that you master API parameters, proceed to GraphQL Setup to learn how to install and use Strapi's Graphql plugin for flexible querying. After that, explore API Customization for custom controllers and routes.
Related lessons:
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro