Skip to content

Query API

The plugin provides a GROQ-like query API under /wp-json/wp-portable-text/v1/ that lets you search and extract Portable Text content across posts.

Tests for the Query API are documented in QUERY-TESTS.md with live results from a test site.

EndpointDescription
GET /wp-json/wp-portable-text/v1/queryFind posts matching block/content criteria
GET /wp-json/wp-portable-text/v1/blocksExtract specific blocks across posts

/query — Find posts by content structure

Section titled “/query — Find posts by content structure”

Find posts that contain specific block types, styles, or marks.

Parameters:

ParameterTypeDefaultDescription
post_typestringpostPost type to search
block_typestringFilter by block _type: block, image, codeBlock, embed, table, break
hasstringFilter posts containing this mark or annotation (e.g., link, strong, em)
stylestringFilter posts containing blocks with this style (e.g., h1, h2, blockquote)
per_pageinteger10Results per page (max 100)
pageinteger1Page number

Response headers: X-WP-Total, X-WP-TotalPages, X-WP-PT-Cache (HIT or MISS)

Examples:

Find all posts containing images:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/query?block_type=image" | jq .
[
{
"id": 42,
"title": "My Photo Post",
"date": "2026-04-10 12:00:00",
"link": "https://example.com/my-photo-post/",
"portable_text": [ ... ],
"matched_blocks": [
{
"_type": "image",
"_key": "img1",
"src": "https://example.com/wp-content/uploads/photo.jpg",
"alt": "A photo"
}
]
}
]

Find posts containing links:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/query?has=link"

Find posts with h2 headings:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/query?style=h2"

Find posts using bold text:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/query?has=strong"

Search pages instead of posts:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/query?post_type=page&block_type=codeBlock"

Returns a flat list of blocks (with post context) matching the criteria. Useful for building indexes, galleries, or aggregations.

Parameters:

ParameterTypeDefaultDescription
post_typestringpostPost type to search
block_typestringrequiredBlock type to extract: block, image, codeBlock, embed, table, break
languagestringFilter code blocks by language
stylestringFilter text blocks by style
per_pageinteger20Results per page (max 100)
pageinteger1Page number

Response headers: X-WP-Total, X-WP-TotalPages, X-WP-PT-Cache (HIT or MISS)

Examples:

Get all images across all posts (e.g., for a site-wide gallery):

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/blocks?block_type=image" | jq .
[
{
"block": {
"_type": "image",
"_key": "img1",
"src": "https://example.com/wp-content/uploads/sunset.jpg",
"alt": "Sunset over the lake",
"caption": "Photo by Jane Doe"
},
"post_id": 42,
"title": "Weekend Trip",
"link": "https://example.com/weekend-trip/"
},
{
"block": {
"_type": "image",
"_key": "img2",
"src": "https://example.com/wp-content/uploads/mountain.jpg",
"alt": "Mountain view"
},
"post_id": 55,
"title": "Hiking Guide",
"link": "https://example.com/hiking-guide/"
}
]

Get all PHP code blocks:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/blocks?block_type=codeBlock&language=php"

Get all JavaScript code blocks:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/blocks?block_type=codeBlock&language=javascript"

Get all h2 headings across posts:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/blocks?block_type=block&style=h2"

Paginate through results:

Terminal window
curl -s "https://example.com/wp-json/wp-portable-text/v1/blocks?block_type=image&per_page=5&page=2"

Build a site-wide image gallery:

const response = await fetch('/wp-json/wp-portable-text/v1/blocks?block_type=image&per_page=50');
const images = await response.json();
const total = response.headers.get('X-WP-Total');
images.forEach(({ block, title, link }) => {
console.log(`${block.alt} — from "${title}" (${link})`);
});

Find posts with code snippets in a specific language:

const response = await fetch('/wp-json/wp-portable-text/v1/query?block_type=codeBlock');
const posts = await response.json();
posts.forEach(post => {
const codeBlocks = post.matched_blocks;
console.log(`${post.title}: ${codeBlocks.length} code block(s)`);
});