From redaxo-core
Builds HTTP/AJAX endpoints in REDAXO using rex_api_function for custom addons, including lib/class setup, published flag for frontend access, JSON responses, CORS headers, and rex-api-call URLs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/redaxo-core:redaxo-api-functionsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`rex_api_function` is the built-in REDAXO mechanism for HTTP/AJAX endpoints from your own addon. Each endpoint is a class under `lib/` that extends `rex_api_function`. URL: `/index.php?rex-api-call=<class_suffix>`.
rex_api_function Endpointsrex_api_function is the built-in REDAXO mechanism for HTTP/AJAX endpoints from your own addon. Each endpoint is a class under lib/ that extends rex_api_function. URL: /index.php?rex-api-call=<class_suffix>.
This is not the same as the FriendsOfRedaxo/api addon (which is a full REST framework with route table, OpenAPI, etc.). rex_api_function is the lower-level core feature — perfect for one-off AJAX endpoints in a single addon.
<?php
// lib/api/save_item.php
class rex_api_my_addon_save_item extends rex_api_function
{
protected $published = true; // true = callable from frontend; false = backend only
public function execute()
{
// For JSON request bodies:
$input = json_decode(file_get_contents('php://input'), true);
if (!is_array($input)) {
rex_response::cleanOutputBuffers();
rex_response::setStatus(400);
rex_response::sendJson(['error' => 'Invalid JSON']);
exit;
}
// ...do work...
$result = ['id' => 42, 'saved' => true];
rex_response::cleanOutputBuffers();
rex_response::setStatus(200);
rex_response::sendJson(['data' => $result]);
exit;
}
}
lib/ directory of your addon (autoloaded by REDAXO)rex_api_ — without this, REDAXO doesn't dispatch to it$published flag:
true – endpoint reachable from frontend (no login required)false (default) – only callable when a backend user is logged inexit after sendJson() – REDAXO appends HTML otherwiseGET/POST /index.php?rex-api-call=my_addon_save_item
The URL suffix matches the part of the class name after rex_api_. So rex_api_my_addon_save_item → ?rex-api-call=my_addon_save_item.
When the endpoint is called from a different origin (e.g. an embedded widget on a third-party site), set CORS headers before any output:
public function execute()
{
rex_response::cleanOutputBuffers();
// CORS preflight + actual response headers
header('Access-Control-Allow-Origin: ' . ($_SERVER['HTTP_ORIGIN'] ?? '*'));
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
rex_response::setStatus(204);
exit;
}
// ...handle the actual request...
}
For tighter security, allowlist origins:
$allowed = ['https://partner1.com', 'https://partner2.com'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed, true)) {
header('Access-Control-Allow-Origin: ' . $origin);
}
| Source | Code | Notes |
|---|---|---|
| Query string | rex_request::get('id', 'int', 0) | Type-coerced |
| Form body | rex_request::post('name', 'string', '') | Type-coerced |
| JSON body | json_decode(file_get_contents('php://input'), true) | Validate before use |
| Header | $_SERVER['HTTP_AUTHORIZATION'] ?? '' | Apache may strip — see below |
rex_request::get() / rex_request::post() give you type safety for free — prefer them over reading $_GET/$_POST directly.
AuthorizationIf your endpoint reads a Bearer token from the Authorization header and Apache strips it, add to .htaccess:
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
$published = false (or omitting it) and wondering why frontend AJAX gets 403 – set it to true for frontend endpoints.exit after sendJson() – the response gets the JSON, then a blob of REDAXO's normal HTML appended. Browsers parse this as malformed JSON.sendJson() – headers can't be sent after body. Set them first.rex_response::cleanOutputBuffers() – stray output from boot.php (warnings, debug dump() calls) leaks into the response.rex_config::get('my_addon', 'api_key').rex_api_my_addon_save_item must be called as ?rex-api-call=my_addon_save_item, not save_item or my_addon/save_item.$_POST – $_POST is only populated for application/x-www-form-urlencoded or multipart/form-data. For application/json, read php://input.Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub friendsofredaxo/claude-marketplace --plugin redaxo-core