REST API
The WidgetCore search REST endpoint — the route, every parameter with its type and default, the response shape, pagination headers, request examples and the status codes.
The search widget and the shortcode both talk to a single REST endpoint. You can call it yourself from JavaScript, from a mobile app or from another plugin.
The endpoint
| Item | Value |
|---|---|
| Namespace | wgcr/v1 |
| Route | /search |
| Full address | https://example.com/wp-json/wgcr/v1/search |
| Method | GET |
| Permission callback | __return_true (public) |
| Result cap | WGCR_SEARCH_MAX_RESULTS (50) |
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | — | Required; the search query, at least 2 characters |
type | string | post | The source post type |
limit | number | 5 | Number of results; clamped to 1–50 |
template | number | 0 | Elementor template id used to render results |
page | number | 0 | Page number; when greater than 0 the count headers are returned |
orderby | string | relevance | relevance, date, title, author, rand, menu_order |
order | string | DESC | ASC or DESC |
date | string | all | all, week, month, year |
terms | string | Empty | A comma separated list of [taxonomy:]id |
terms_op | string | exclude | include or exclude |
ignore_sticky | number | 1 | 1 means sticky posts are not given priority |
query_id | string | Empty | The key for the wgcr_search_query_args/{query_id} filter |
q validation: if it is not a string, or shorter than 2 characters after trim, the response is a rest_invalid_param error.
The response shape
[
{
"id": 42,
"title": "Getting started with the course",
"link": "https://example.com/?p=42",
"thumb": "https://example.com/wp-content/uploads/2026/09/cover-150x150.jpg",
"excerpt": "A short text of about 18 words…",
"date": "2026-09-01"
}
]
| Field | Type | Notes |
|---|---|---|
id | number | Post id |
title | string | Escaped title text |
link | string | Permalink |
thumb | string or null | Thumbnail URL, null when there is none |
excerpt | string | Excerpt with an ellipsis, empty when turned off |
date | string | Publish date in Y-m-d format |
html | string | Only with template: the rendered Elementor template |
Pagination headers
When page is greater than 0, two standard WordPress headers are added to the response:
X-WP-Total: 87
X-WP-TotalPages: 8
| Header | Meaning |
|---|---|
X-WP-Total | Total number of matching posts |
X-WP-TotalPages | Total number of pages at the requested limit |
Examples
One request, four flavours — pick the tab that matches your stack.
curl -s "https://example.com/wp-json/wgcr/v1/search?q=course&limit=5&type=post"
# With pagination, reading the count headers
curl -sD - -o /dev/null "https://example.com/wp-json/wgcr/v1/search?q=course&limit=12&page=2" | grep -i "^x-wp"const url = new URL('/wp-json/wgcr/v1/search', window.location.origin);
url.searchParams.set('q', 'course');
url.searchParams.set('limit', '8');
url.searchParams.set('page', '1');
const res = await fetch(url, { headers: { Accept: 'application/json' } });
const items = await res.json();
const total = Number(res.headers.get('X-WP-Total') || 0);
const pages = Number(res.headers.get('X-WP-TotalPages') || 0);
items.forEach((item) => {
console.log(item.title, item.link, item.thumb);
});url.searchParams.set('terms', 'category:12,category:18');
url.searchParams.set('terms_op', 'include');
url.searchParams.set('orderby', 'date');
url.searchParams.set('order', 'DESC');url.searchParams.set('template', '1482');When template is valid, every result carries an extra html field with that template rendered for that post. If the template is a draft or renders no visible content, html is not returned.
Server-side behaviour
| Step | What happens |
|---|---|
| 1 | q is validated (at least 2 characters) |
| 2 | type is sanitised; invalid values become post |
| 3 | limit is clamped to 1…WGCR_SEARCH_MAX_RESULTS |
| 4 | orderby, order, date, terms, terms_op are whitelisted |
| 5 | The query args are built: post_status => publish, has_password => false |
| 6 | The wgcr_search_query_args filter runs, then the {query_id} variant |
| 7 | WP_Query runs and the results are mapped into the response fields |
| 8 | With template, each post is rendered through Elementor |
| 9 | With page > 0, the count headers are added |
Status codes
| Status | When |
|---|---|
200 | A successful search (an empty array is still a success) |
400 | q missing or shorter than 2 characters (rest_invalid_param) |
404 | The REST API itself is unavailable or permalinks block it |
An empty result is not an error: you get 200 with [], and the client shows the “No results found.” message.
Rate limiting and optimisation
The plugin adds no rate limiting of its own. On a busy site consider these measures:
| Measure | Effect |
|---|---|
| Cache the route for anonymous users (short TTL) | Fewer queries for popular terms |
Keep limit at or below 12 | Smaller payloads |
| Turn thumbnails off | Fewer image requests |
| Add an index for your search-heavy post type | Faster WP_Query |
Use query_id + a filter to narrow the query before it runs | Less work in the database |