Querying Data: Filtering, Pagination & Embedding
Query Parameters
The REST API accepts URL parameters to filter and customize responses.
Pagination
Control how many results you get:
# Get 5 posts per page
/wp-json/wp/v2/posts?per_page=5
# Get page 2 of results
/wp-json/wp/v2/posts?per_page=5&page=2
# Maximum per_page is 100
/wp-json/wp/v2/posts?per_page=100Handling Pagination in JavaScript
async function getAllPosts() {
const allPosts = [];
let page = 1;
let totalPages = 1;
do {
const response = await fetch(`/wp-json/wp/v2/posts?per_page=100&page=${page}`);
const posts = await response.json();
totalPages = parseInt(response.headers.get('X-WP-TotalPages'));
allPosts.push(...posts);
page++;
} while (page <= totalPages);
return allPosts;
}Filtering by Fields
By Category or Tag
# Posts in category ID 5
/wp-json/wp/v2/posts?categories=5
# Posts in multiple categories (OR)
/wp-json/wp/v2/posts?categories=5,6,7
# Posts with tag ID 10
/wp-json/wp/v2/posts?tags=10
# Combine filters (AND)
/wp-json/wp/v2/posts?categories=5&tags=10By Author
# Posts by author ID 1
/wp-json/wp/v2/posts?author=1
# Exclude an author
/wp-json/wp/v2/posts?author_exclude=2By Status
# Published posts (default)
/wp-json/wp/v2/posts?status=publish
# Draft posts (requires authentication)
/wp-json/wp/v2/posts?status=draft
# Multiple statuses
/wp-json/wp/v2/posts?status=publish,draftBy Date
# Posts after a date
/wp-json/wp/v2/posts?after=2026-01-01T00:00:00
# Posts before a date
/wp-json/wp/v2/posts?before=2026-12-31T23:59:59
# Posts in a date range
/wp-json/wp/v2/posts?after=2026-01-01&before=2026-06-30Searching
# Search posts
/wp-json/wp/v2/posts?search=wordpress
# Search is performed on title, content, and excerpt
Note: Search is case-insensitive but may be slow on large sites. Consider using a dedicated search plugin with API support.
Ordering Results
# Order by date (default: descending)
/wp-json/wp/v2/posts?orderby=date&order=desc
# Order by title alphabetically
/wp-json/wp/v2/posts?orderby=title&order=asc
# Order by menu_order (for pages)
/wp-json/wp/v2/pages?orderby=menu_order&order=ascAvailable orderby values
| Value | Description |
|---|---|
date | Post date |
modified | Last modified date |
title | Alphabetical title |
slug | Alphabetical slug |
id | Post ID |
author | Author ID |
relevance | Search relevance (with search param) |
menu_order | Page menu order |
Selecting Specific Fields
Reduce response size by requesting only needed fields:
# Only get id, title, and link
/wp-json/wp/v2/posts?_fields=id,title,link
# Useful for performance
/wp-json/wp/v2/posts?_fields=id,title,excerpt,featured_mediaResponse with _fields
[
{
"id": 123,
"title": {"rendered": "My Post"},
"link": "https://site.com/my-post/"
}
]Embedding Related Data
Instead of making multiple requests, embed related resources:
# Embed author, featured image, terms
/wp-json/wp/v2/posts?_embed
# The response now includes _embedded objectEmbedded Response Structure
{
"id": 123,
"title": {"rendered": "My Post"},
"featured_media": 456,
"_embedded": {
"author": [{
"id": 1,
"name": "John Doe",
"avatar_urls": {...}
}],
"wp:featuredmedia": [{
"id": 456,
"source_url": "https://site.com/image.jpg",
"media_details": {...}
}],
"wp:term": [
[{"id": 5, "name": "Category Name"}],
[{"id": 10, "name": "Tag Name"}]
]
}
}Practical Example: Blog Listing
async function getBlogPosts(options = {}) {
const {
page = 1,
perPage = 10,
category = null,
search = null
} = options;
const params = new URLSearchParams({
page,
per_page: perPage,
_embed: true,
_fields: 'id,title,excerpt,link,date,featured_media,_links'
});
if (category) params.append('categories', category);
if (search) params.append('search', search);
const response = await fetch(`/wp-json/wp/v2/posts?${params}`);
return {
posts: await response.json(),
total: parseInt(response.headers.get('X-WP-Total')),
totalPages: parseInt(response.headers.get('X-WP-TotalPages'))
};
}
// Usage
const { posts, total, totalPages } = await getBlogPosts({
page: 1,
perPage: 12,
category: 5
});Filtering Custom Post Types
Custom post types are exposed at their own endpoints:
# Products (WooCommerce)
/wp-json/wc/v3/products
# Custom post type "events"
/wp-json/wp/v2/events?status=publish&orderby=date
Tip: Custom post types need
'show_in_rest' => true in their registration to appear in the API.
Next Steps
In the next lesson, we'll learn how to authenticate requests and perform write operations โ creating, updating, and deleting content.
๐ฏ Lesson Complete! You can now query WordPress data with advanced filtering, pagination, and embedding.