API filter hooks
Filter hooks that let plugins modify the public JSON API response — add fields, remove data, or reshape the output.
These filter hooks run inside the public JSON API (/api/v1/content/…). Use them to add custom fields, remove sensitive data, or reshape the response — without touching core or subclassing the API controller.
See the JSON API reference for the full endpoint documentation.
contensio/api/content-item
Type: Filter
Since: 1.4.0
Source: ContentApiController::formatContent()
Runs on every item in the API response — both the paginated list (GET /api/v1/content/{type}) and the single-entry endpoint (GET /api/v1/content/{type}/{slug}).
The filter receives the fully assembled array for one entry and the corresponding Content model. Return the array — modified or unchanged.
Signature
add_filter('contensio/api/content-item', function (array $data, Content $content): array {
// modify $data
return $data;
}, priority: 10);
Arguments
| # | Name | Type | Description |
|---|---|---|---|
| 1 | $data |
array |
The default response array for this entry (see shape below). |
| 2 | $content |
Content |
The full Eloquent model with relations. |
Default response shape
[
'id' => int,
'status' => string, // 'published'
'published_at' => string|null, // ISO 8601
'created_at' => string, // ISO 8601
'author' => ['id' => int, 'name' => string] | null,
'title' => string|null,
'slug' => string|null,
'excerpt' => string|null,
'meta_title' => string|null,
'meta_description' => string|null,
'featured_image' => [
'url' => string,
'thumbnail' => string,
'medium' => string,
] | null,
'terms' => [
['id' => int, 'name' => string, 'slug' => string],
// ...
],
]
Example — add a custom field to every response
use Contensio\Models\Content;
add_filter('contensio/api/content-item', function (array $data, Content $content): array {
$data['reading_time'] = max(1, (int) ceil(
str_word_count(strip_tags($data['excerpt'] ?? '')) / 200
));
return $data;
});
Example — expose a custom field value
add_filter('contensio/api/content-item', function (array $data, Content $content): array {
$data['price'] = $content->field('price');
return $data;
});
Example — strip a field for unauthenticated consumers
add_filter('contensio/api/content-item', function (array $data, Content $content): array {
if (! request()->hasHeader('X-Api-Key')) {
unset($data['meta_title'], $data['meta_description']);
}
return $data;
});
Example — add a sponsored badge based on taxonomy
add_filter('contensio/api/content-item', function (array $data, Content $content): array {
$isSponsor = $content->terms->contains(fn ($t) =>
$t->translations->first()?->slug === 'sponsored'
);
$data['sponsored'] = $isSponsor;
return $data;
});
Notes
- Always return the array. A filter that returns
nullreplaces the entire item withnullin the response. - The filter runs on every item in a list response — keep callbacks fast. Cache expensive lookups if needed.
- The
$contentmodel hastranslations,author,terms,featuredImage, andfieldValueseager-loaded. Accessing any other relation will trigger an additional query per item. - Multiple plugins can register for this filter. They run in priority order, each receiving the output of the previous. The final array is what the API returns.