ProcessWire API for Content Management
ProcessWire is a PHP CMS with its own API for working with content directly in PHP templates. The API is based on method chaining ($pages->find()) and allows complex queries without SQL. For headless mode, use the ProcessWire GraphQL module or custom REST endpoint.
Built-in PHP API
ProcessWire uses $pages, $page, $user, $config as global variables in templates:
// templates/blog.php
// Selection with filters and pagination
$limit = 12;
$start = ($input->pageNum - 1) * $limit;
$posts = $pages->find("template=blog-post, status=published, sort=-date, limit=$limit, start=$start");
$totalPosts = $pages->count("template=blog-post, status=published");
// Selection with field conditions
$featuredPosts = $pages->find("
template=blog-post,
featured=1,
date>=today,
category.name%=Web Development,
sort=-date,
limit=3
");
// Single item
$post = $pages->get("template=blog-post, slug=my-post-slug");
if (!$post->id) wire404();
Selector String — query language
// Text search
$pages->find("template=product, title*=laptop, sort=title");
// Numeric conditions
$pages->find("template=product, price>=1000, price<=5000");
// Date
$pages->find("template=event, event_date>=today, sort=event_date");
// OR conditions
$pages->find("template=post, (category=tech|category=science)");
// Related pages
$pages->find("template=product, categories.id={$category->id}");
// Full-text search
$pages->find("title|body~=search query, template=post");
// Sort by custom field
$pages->find("template=product, sort=-rating, sort=title");
REST API via template-router
ProcessWire doesn't have built-in REST API. Create via template-router:
// site/templates/api.php
// URL: /api/blog/?page=1&limit=10
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: ' . $config->httpHost);
// Simple authorization by key
$apiKey = $input->get->text('key');
if ($apiKey !== $config->apiKey) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
return;
}
$page_num = (int) $input->get->int('page') ?: 1;
$limit = min((int) $input->get->int('limit') ?: 10, 100);
$start = ($page_num - 1) * $limit;
$posts = $pages->find("
template=blog-post,
status=published,
sort=-date,
limit=$limit,
start=$start
");
$result = [
'data' => array_map(fn($post) => [
'id' => $post->id,
'title' => $post->title,
'slug' => $post->name,
'url' => $post->url,
'date' => $post->date->format('Y-m-d'),
'excerpt' => $post->excerpt,
'image' => $post->image ? [
'url' => $post->image->width(800)->url,
'width' => 800,
'height' => (int) round(800 / $post->image->ratio),
] : null,
], $posts->getArray()),
'total' => $posts->getTotal(),
'page' => $page_num,
'limit' => $limit,
];
echo json_encode($result);
ProcessWire GraphQL Module
# Installation via ProcessWire modules
# Download from processwire.com/modules/processwire-graphql/
# In config.php — access configuration
$config->graphql = [
'templateFilters' => ['blog-post', 'product', 'category'],
'fieldFilters' => ['title', 'body', 'date', 'image', 'category'],
'maxLimit' => 100,
];
query {
blogPost(s: "status=published, sort=-date, limit=10") {
list {
id
title
date
body
image { url(width: 800) }
category { title url }
}
total
}
}
Response caching
// Cache via WireCache
$cacheKey = "api_posts_page{$page_num}";
$cached = $cache->get($cacheKey);
if ($cached) {
echo $cached;
return;
}
// ... forming $result ...
$json = json_encode($result);
$cache->save($cacheKey, $json, 3600); // 1 hour
echo $json;
Creating basic REST API on ProcessWire (5–7 endpoints) — 2–4 days.







