initial
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: wp-rest-api
|
||||
description: "Use when building, extending, or debugging WordPress REST API endpoints/routes: register_rest_route, WP_REST_Controller/controller classes, schema/argument validation, permission_callback/authentication, response shaping, register_rest_field/register_meta, or exposing CPTs/taxonomies via show_in_rest."
|
||||
compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Filesystem-based agent with bash + node. Some workflows require WP-CLI."
|
||||
---
|
||||
|
||||
# WP REST API
|
||||
|
||||
## When to use
|
||||
|
||||
Use this skill when you need to:
|
||||
|
||||
- create or update REST routes/endpoints
|
||||
- debug 401/403/404 errors or permission/nonce issues
|
||||
- add custom fields/meta to REST responses
|
||||
- expose custom post types or taxonomies via REST
|
||||
- implement schema + argument validation
|
||||
- adjust response links/embedding/pagination
|
||||
|
||||
## Inputs required
|
||||
|
||||
- Repo root + target plugin/theme/mu-plugin (path to entrypoint).
|
||||
- Desired namespace + version (e.g. `my-plugin/v1`) and routes.
|
||||
- Authentication mode (cookie + nonce vs application passwords vs auth plugin).
|
||||
- Target WordPress version constraints (if below 6.9, call out).
|
||||
|
||||
## Procedure
|
||||
|
||||
### 0) Triage and locate REST usage
|
||||
|
||||
1. Run triage:
|
||||
- `node skills/wp-project-triage/scripts/detect_wp_project.mjs`
|
||||
2. Search for existing REST usage:
|
||||
- `register_rest_route`
|
||||
- `WP_REST_Controller`
|
||||
- `rest_api_init`
|
||||
- `show_in_rest`, `rest_base`, `rest_controller_class`
|
||||
|
||||
If this is a full site repo, pick the specific plugin/theme before changing code.
|
||||
|
||||
### 1) Choose the right approach
|
||||
|
||||
- **Expose CPT/taxonomy in `wp/v2`:**
|
||||
- Use `show_in_rest => true` + `rest_base` if needed.
|
||||
- Optionally provide `rest_controller_class`.
|
||||
- Read `references/custom-content-types.md`.
|
||||
- **Custom endpoints:**
|
||||
- Use `register_rest_route()` on `rest_api_init`.
|
||||
- Prefer a controller class (`WP_REST_Controller` subclass) for anything non-trivial.
|
||||
- Read `references/routes-and-endpoints.md` and `references/schema.md`.
|
||||
|
||||
### 2) Register routes safely (namespaces, methods, permissions)
|
||||
|
||||
- Use a unique namespace `vendor/v1`; avoid `wp/*` unless core.
|
||||
- Always provide `permission_callback` (use `__return_true` for public endpoints).
|
||||
- Use `WP_REST_Server::READABLE/CREATABLE/EDITABLE/DELETABLE` constants.
|
||||
- Return data via `rest_ensure_response()` or `WP_REST_Response`.
|
||||
- Return errors via `WP_Error` with an explicit `status`.
|
||||
|
||||
Read `references/routes-and-endpoints.md`.
|
||||
|
||||
### 3) Validate/sanitize request args
|
||||
|
||||
- Define `args` with `type`, `default`, `required`, `validate_callback`, `sanitize_callback`.
|
||||
- Prefer JSON Schema validation with `rest_validate_value_from_schema` then `rest_sanitize_value_from_schema`.
|
||||
- Never read `$_GET`/`$_POST` directly inside endpoints; use `WP_REST_Request`.
|
||||
|
||||
Read `references/schema.md`.
|
||||
|
||||
### 4) Responses, fields, and links
|
||||
|
||||
- Do **not** remove core fields from default endpoints; add fields instead.
|
||||
- Use `register_rest_field` for computed fields; `register_meta` with `show_in_rest` for meta.
|
||||
- For `object`/`array` meta, define schema in `show_in_rest.schema`.
|
||||
- If you need unfiltered post content (e.g., ToC plugins injecting HTML), request `?context=edit` to access `content.raw` (auth required). Pair with `_fields=content.raw` to keep responses small.
|
||||
- Add related resource links via `WP_REST_Response::add_link()`.
|
||||
|
||||
Read `references/responses-and-fields.md`.
|
||||
|
||||
### 5) Authentication and authorization
|
||||
|
||||
- For wp-admin/JS: cookie auth + `X-WP-Nonce` (action `wp_rest`).
|
||||
- For external clients: application passwords (basic auth) or an auth plugin.
|
||||
- Use capability checks in `permission_callback` (authorization), not just “logged in”.
|
||||
|
||||
Read `references/authentication.md`.
|
||||
|
||||
### 6) Client-facing behavior (discovery, pagination, embeds)
|
||||
|
||||
- Ensure discovery works (`Link` header or `<link rel="https://api.w.org/">`).
|
||||
- Support `_fields`, `_embed`, `_method`, `_envelope`, pagination headers.
|
||||
- Remember `per_page` is capped at 100.
|
||||
|
||||
Read `references/discovery-and-params.md`.
|
||||
|
||||
## Verification
|
||||
|
||||
- `/wp-json/` index includes your namespace.
|
||||
- `OPTIONS` on your route returns schema (when provided).
|
||||
- Endpoint returns expected data; permission failures return 401/403 as appropriate.
|
||||
- CPT/taxonomy routes appear under `wp/v2` when `show_in_rest` is true.
|
||||
- Run repo lint/tests and any PHP/JS build steps.
|
||||
|
||||
## Failure modes / debugging
|
||||
|
||||
- 404: `rest_api_init` not firing, route typo, or permalinks off (use `?rest_route=`).
|
||||
- 401/403: missing nonce/auth, or `permission_callback` too strict.
|
||||
- `_doing_it_wrong` for missing `permission_callback`: add it (use `__return_true` if public).
|
||||
- Invalid params: missing/incorrect `args` schema or validation callbacks.
|
||||
- Fields missing: `show_in_rest` false, meta not registered, or CPT lacks `custom-fields` support.
|
||||
|
||||
## Escalation
|
||||
|
||||
If version support or behavior is unclear, consult the REST API Handbook and core docs before inventing patterns.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Authentication (summary)
|
||||
|
||||
## Cookie authentication (in-dashboard / same-site)
|
||||
|
||||
- Standard for wp-admin and theme/plugin JS.
|
||||
- Requires a REST nonce (`wp_rest`) sent as `X-WP-Nonce` header or `_wpnonce` param.
|
||||
- If the nonce is missing, the request is treated as unauthenticated even if cookies exist.
|
||||
|
||||
## Application Passwords (external clients)
|
||||
|
||||
- Available in WordPress 5.6+.
|
||||
- Use HTTPS + Basic Auth with the application password.
|
||||
- Recommended over the legacy Basic Auth plugin.
|
||||
|
||||
## Auth plugins
|
||||
|
||||
- OAuth 1.0a or JWT plugins are common for external apps.
|
||||
- Use only if required; follow plugin docs and security guidance.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Custom Content Types (summary)
|
||||
|
||||
## Custom post types
|
||||
|
||||
- Set `show_in_rest => true` in `register_post_type()` to expose in `wp/v2`.
|
||||
- Use `rest_base` to change the route slug.
|
||||
- Optionally set `rest_controller_class` (must extend `WP_REST_Controller`).
|
||||
|
||||
## Custom taxonomies
|
||||
|
||||
- Set `show_in_rest => true` in `register_taxonomy()`.
|
||||
- Use `rest_base` and optional `rest_controller_class` (default `WP_REST_Terms_Controller`).
|
||||
|
||||
## Adding REST support to existing types
|
||||
|
||||
- Use `register_post_type_args` or `register_taxonomy_args` filters to enable `show_in_rest` for types you do not control.
|
||||
|
||||
## Discovery links for custom controllers
|
||||
|
||||
- If you use a custom controller class, use `rest_route_for_post` or `rest_route_for_term` filters to map objects to routes.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Discovery and Global Parameters (summary)
|
||||
|
||||
## API discovery
|
||||
|
||||
- REST API root is discovered via the `Link` header: `rel="https://api.w.org/"`.
|
||||
- HTML pages also include a `<link rel="https://api.w.org/" href="...">` element.
|
||||
- For non-pretty permalinks, use `?rest_route=/`.
|
||||
|
||||
## Global parameters
|
||||
|
||||
- `_fields` limits response fields (supports nested meta keys).
|
||||
- `_embed` includes linked resources in `_embedded`.
|
||||
- `_method` or `X-HTTP-Method-Override` allows POST to simulate PUT/DELETE.
|
||||
- `_envelope` puts headers/status in the response body.
|
||||
- `_jsonp` enables JSONP for legacy clients.
|
||||
|
||||
## Pagination
|
||||
|
||||
- Collections accept `page`, `per_page` (1-100), and `offset`.
|
||||
- Pagination headers: `X-WP-Total` and `X-WP-TotalPages`.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Responses and Fields (summary)
|
||||
|
||||
## Do not remove core fields
|
||||
|
||||
- Removing or changing core fields breaks clients (including wp-admin).
|
||||
- Prefer adding new fields or using `_fields` to limit response size.
|
||||
|
||||
## register_rest_field
|
||||
|
||||
- Use for computed or custom fields.
|
||||
- Provide `get_callback`, optional `update_callback`, and `schema`.
|
||||
- Register on `rest_api_init`.
|
||||
|
||||
## Raw vs rendered content
|
||||
|
||||
- For posts, `content.rendered` reflects filters (plugins like ToC inject HTML).
|
||||
- Use `?context=edit` (authenticated) to access `content.raw`.
|
||||
- Combine with `_fields=content.raw` when you only need the editable body.
|
||||
|
||||
## register_meta / register_post_meta / register_term_meta
|
||||
|
||||
- Use when the data is stored as meta.
|
||||
- Set `show_in_rest => true` to expose under `.meta`.
|
||||
- For `object` or `array` types, provide a JSON schema in `show_in_rest.schema`.
|
||||
|
||||
## Links and embedding
|
||||
|
||||
- Add links with `WP_REST_Response::add_link( $rel, $href, $attrs )`.
|
||||
- Use `embeddable => true` to allow `_embed`.
|
||||
- Use IANA rels or a custom URI relation; CURIEs can be registered via `rest_response_link_curies`.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Routes and Endpoints (summary)
|
||||
|
||||
## Registering routes
|
||||
|
||||
- Register routes on the `rest_api_init` hook with `register_rest_route( $namespace, $route, $args )`.
|
||||
- A **route** is the URL pattern; an **endpoint** is the method + callback bound to that route.
|
||||
- For non-pretty permalinks, the route is accessed via `?rest_route=/namespace/route`.
|
||||
|
||||
## Namespacing
|
||||
|
||||
- Always namespace routes (`vendor/v1`).
|
||||
- **Do not** use the `wp/*` namespace unless you are targeting core.
|
||||
|
||||
## Methods
|
||||
|
||||
- Use `WP_REST_Server::READABLE` (GET), `CREATABLE` (POST), `EDITABLE` (PUT/PATCH), `DELETABLE` (DELETE).
|
||||
- Multiple endpoints can share a route, one per method.
|
||||
|
||||
## permission_callback (required)
|
||||
|
||||
- Always provide `permission_callback`.
|
||||
- Public endpoints should use `__return_true`.
|
||||
- For restricted endpoints, use capability checks (`current_user_can`) or object-level authorization.
|
||||
- Missing `permission_callback` emits a `_doing_it_wrong` notice in modern WP.
|
||||
|
||||
## Arguments
|
||||
|
||||
- Register `args` to validate and sanitize inputs.
|
||||
- Use `type`, `required`, `default`, `validate_callback`, `sanitize_callback`.
|
||||
- Access params via the `WP_REST_Request` object, not `$_GET`/`$_POST`.
|
||||
|
||||
## Return values
|
||||
|
||||
- Return data via `rest_ensure_response()` or a `WP_REST_Response`.
|
||||
- Return `WP_Error` with a `status` in `data` for error responses.
|
||||
- Do not call `wp_send_json()` in REST callbacks.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Schema and Argument Validation (summary)
|
||||
|
||||
## JSON Schema in WordPress
|
||||
|
||||
- REST API uses JSON Schema (draft 4 subset) for resource and argument definitions.
|
||||
- Provide schema via `get_item_schema()` on controllers or `schema` callbacks on routes.
|
||||
- Schema enables discovery (`OPTIONS`) and validation.
|
||||
|
||||
## Validation + sanitization
|
||||
|
||||
- Use `rest_validate_value_from_schema( $value, $schema )` then `rest_sanitize_value_from_schema( $value, $schema )`.
|
||||
- If you override `sanitize_callback`, built-in schema validation will not run; use `rest_validate_request_arg` to keep it.
|
||||
- `WP_REST_Controller::get_endpoint_args_for_item_schema()` wires validation automatically.
|
||||
|
||||
## Schema caching
|
||||
|
||||
- Cache the generated schema on the controller instance (`$this->schema`) to avoid recomputation.
|
||||
|
||||
## Formats and types
|
||||
|
||||
- Common formats: `date-time`, `uri`, `email`, `ip`, `uuid`, `hex-color`.
|
||||
- For `array` and `object` types, you must define `items` or `properties` schemas.
|
||||
Reference in New Issue
Block a user