From redaxo-yform
Exposes YForm tables as JSON:API REST endpoints via PHP routes, with GET filtering/pagination/sorting, POST/DELETE CRUD, token auth, and field whitelists. For configuring YForm-backed APIs serving SPAs.
How this skill is triggered — by the user, by Claude, or both
Slash command
/redaxo-yform:yform-rest-apiThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
YForm includes a REST layer that exposes a YForm-backed dataset class as JSON:API endpoints. Authentication is token-based; routes are versioned by path; per-method field whitelists control what's readable / writable.
YForm includes a REST layer that exposes a YForm-backed dataset class as JSON:API endpoints. Authentication is token-based; routes are versioned by path; per-method field whitelists control what's readable / writable.
In your project addon's boot.php:
$route = new \rex_yform_rest_route([
'path' => '/v1/articles/',
'auth' => '\rex_yform_rest_auth_token::checkToken',
'type' => MyArticle::class,
'query' => MyArticle::query(),
'get' => [
MyArticle::class => [
'fields' => ['id', 'title', 'text', 'status'],
],
],
'post' => [
MyArticle::class => [
'fields' => ['title', 'text', 'status'],
],
],
'delete' => [
MyArticle::class => [
'fields' => ['id'],
],
],
]);
\rex_yform_rest::addRoute($route);
MyArticle must be a rex_yform_manager_dataset subclass registered with setModelClass(). The query value gives you a starting point — add where() clauses there to scope what the endpoint exposes.
All routes live under /rest/. With the example above, the endpoint URL is:
GET /rest/v1/articles/
POST /rest/v1/articles/
DELETE /rest/v1/articles/?filter[id]=5
| Parameter | Description | Example |
|---|---|---|
filter[field]=value | Filter records | ?filter[status]=1 |
include=relation | Include related dataset(s) | ?include=category |
per_page=N | Items per page | ?per_page=10 |
page=N | Page number | ?page=2 |
order[field]=dir | Sort | ?order[created]=desc |
Multiple filters are AND-combined: ?filter[status]=1&filter[clang_id]=1.
{
"data": {
"type": "MyArticle",
"attributes": {
"title": "Neuer Artikel",
"text": "Inhalt...",
"status": 1
}
}
}
The type value must match the class name registered in the route (MyArticle::class). Only fields listed in post.fields are accepted; everything else is ignored.
DELETE /rest/v1/articles/?filter[id]=5
Deletes match the same filter[...] semantics as GET. Be careful with broad filters — the API will happily delete every matching record.
Default is token-based via \rex_yform_rest_auth_token::checkToken. Manage tokens in the backend under YForm → REST → Tokens. Token scopes can be limited to specific routes.
Header:
Authorization: Bearer <token>
For public read-only endpoints, set 'auth' => null — but think hard before doing this; an open POST is an open data-injection target.
Global (applies to every YForm REST route):
\rex_yform_rest::setHeader('Access-Control-Allow-Origin', '*');
Per-route:
$route->setHeader('Access-Control-Allow-Origin', 'https://example.com');
For browser-based SPAs, add:
$route->setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
$route->setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type');
get.fields, post.fields, delete.fields are independent. Practical pattern:
get.fields – everything safe to expose (excluding internal admin notes, soft-delete flags)post.fields – the user-editable subset (excluding id, created_at, status if those are server-controlled)delete.fields – usually just ['id'] for filter purposesAuthorization headerApache strips Authorization by default in some configurations. If valid tokens get rejected with Authorization failed, add to .htaccess:
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
boot.php that fires too late – register in boot.php directly (top level), not inside a callback that runs only on backend requests.setModelClass() – the route serializes plain rex_yform_manager_dataset instead of your subclass, and type mismatches break POST.'auth' => null for "just a quick test" and forgetting to restore it before deploying.post.fields that don't exist on the table – the field gets silently dropped from incoming POSTs.OPTIONS requests fail with no clear error.query start un-scoped – an open MyArticle::query() exposes every row in the table, including drafts and soft-deleted records. Always add baseline where() filters.Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Implements vector databases with Pinecone, Weaviate, Qdrant, Milvus, pgvector for semantic search, RAG, recommendations, and similarity systems. Optimizes embeddings, indexing, and hybrid search.
npx claudepluginhub friendsofredaxo/claude-marketplace --plugin redaxo-yform