|
| 1 | +--- |
| 2 | +name: wp-rest-api |
| 3 | +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." |
| 4 | +compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Filesystem-based agent with bash + node. Some workflows require WP-CLI." |
| 5 | +--- |
| 6 | + |
| 7 | +# WP REST API |
| 8 | + |
| 9 | +## When to use |
| 10 | + |
| 11 | +Use this skill when you need to: |
| 12 | + |
| 13 | +- create or update REST routes/endpoints |
| 14 | +- debug 401/403/404 errors or permission/nonce issues |
| 15 | +- add custom fields/meta to REST responses |
| 16 | +- expose custom post types or taxonomies via REST |
| 17 | +- implement schema + argument validation |
| 18 | +- adjust response links/embedding/pagination |
| 19 | + |
| 20 | +## Inputs required |
| 21 | + |
| 22 | +- Repo root + target plugin/theme/mu-plugin (path to entrypoint). |
| 23 | +- Desired namespace + version (e.g. `my-plugin/v1`) and routes. |
| 24 | +- Authentication mode (cookie + nonce vs application passwords vs auth plugin). |
| 25 | +- Target WordPress version constraints (if below 6.9, call out). |
| 26 | + |
| 27 | +## Procedure |
| 28 | + |
| 29 | +### 0) Triage and locate REST usage |
| 30 | + |
| 31 | +1. Run triage: |
| 32 | + - `node skills/wp-project-triage/scripts/detect_wp_project.mjs` |
| 33 | +2. Search for existing REST usage: |
| 34 | + - `register_rest_route` |
| 35 | + - `WP_REST_Controller` |
| 36 | + - `rest_api_init` |
| 37 | + - `show_in_rest`, `rest_base`, `rest_controller_class` |
| 38 | + |
| 39 | +If this is a full site repo, pick the specific plugin/theme before changing code. |
| 40 | + |
| 41 | +### 1) Choose the right approach |
| 42 | + |
| 43 | +- **Expose CPT/taxonomy in `wp/v2`:** |
| 44 | + - Use `show_in_rest => true` + `rest_base` if needed. |
| 45 | + - Optionally provide `rest_controller_class`. |
| 46 | + - Read `references/custom-content-types.md`. |
| 47 | +- **Custom endpoints:** |
| 48 | + - Use `register_rest_route()` on `rest_api_init`. |
| 49 | + - Prefer a controller class (`WP_REST_Controller` subclass) for anything non-trivial. |
| 50 | + - Read `references/routes-and-endpoints.md` and `references/schema.md`. |
| 51 | + |
| 52 | +### 2) Register routes safely (namespaces, methods, permissions) |
| 53 | + |
| 54 | +- Use a unique namespace `vendor/v1`; avoid `wp/*` unless core. |
| 55 | +- Always provide `permission_callback` (use `__return_true` for public endpoints). |
| 56 | +- Use `WP_REST_Server::READABLE/CREATABLE/EDITABLE/DELETABLE` constants. |
| 57 | +- Return data via `rest_ensure_response()` or `WP_REST_Response`. |
| 58 | +- Return errors via `WP_Error` with an explicit `status`. |
| 59 | + |
| 60 | +Read `references/routes-and-endpoints.md`. |
| 61 | + |
| 62 | +### 3) Validate/sanitize request args |
| 63 | + |
| 64 | +- Define `args` with `type`, `default`, `required`, `validate_callback`, `sanitize_callback`. |
| 65 | +- Prefer JSON Schema validation with `rest_validate_value_from_schema` then `rest_sanitize_value_from_schema`. |
| 66 | +- Never read `$_GET`/`$_POST` directly inside endpoints; use `WP_REST_Request`. |
| 67 | + |
| 68 | +Read `references/schema.md`. |
| 69 | + |
| 70 | +### 4) Responses, fields, and links |
| 71 | + |
| 72 | +- Do **not** remove core fields from default endpoints; add fields instead. |
| 73 | +- Use `register_rest_field` for computed fields; `register_meta` with `show_in_rest` for meta. |
| 74 | +- For `object`/`array` meta, define schema in `show_in_rest.schema`. |
| 75 | +- 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. |
| 76 | +- Add related resource links via `WP_REST_Response::add_link()`. |
| 77 | + |
| 78 | +Read `references/responses-and-fields.md`. |
| 79 | + |
| 80 | +### 5) Authentication and authorization |
| 81 | + |
| 82 | +- For wp-admin/JS: cookie auth + `X-WP-Nonce` (action `wp_rest`). |
| 83 | +- For external clients: application passwords (basic auth) or an auth plugin. |
| 84 | +- Use capability checks in `permission_callback` (authorization), not just “logged in”. |
| 85 | + |
| 86 | +Read `references/authentication.md`. |
| 87 | + |
| 88 | +### 6) Client-facing behavior (discovery, pagination, embeds) |
| 89 | + |
| 90 | +- Ensure discovery works (`Link` header or `<link rel="https://api.w.org/">`). |
| 91 | +- Support `_fields`, `_embed`, `_method`, `_envelope`, pagination headers. |
| 92 | +- Remember `per_page` is capped at 100. |
| 93 | + |
| 94 | +Read `references/discovery-and-params.md`. |
| 95 | + |
| 96 | +## Verification |
| 97 | + |
| 98 | +- `/wp-json/` index includes your namespace. |
| 99 | +- `OPTIONS` on your route returns schema (when provided). |
| 100 | +- Endpoint returns expected data; permission failures return 401/403 as appropriate. |
| 101 | +- CPT/taxonomy routes appear under `wp/v2` when `show_in_rest` is true. |
| 102 | +- Run repo lint/tests and any PHP/JS build steps. |
| 103 | + |
| 104 | +## Failure modes / debugging |
| 105 | + |
| 106 | +- 404: `rest_api_init` not firing, route typo, or permalinks off (use `?rest_route=`). |
| 107 | +- 401/403: missing nonce/auth, or `permission_callback` too strict. |
| 108 | +- `_doing_it_wrong` for missing `permission_callback`: add it (use `__return_true` if public). |
| 109 | +- Invalid params: missing/incorrect `args` schema or validation callbacks. |
| 110 | +- Fields missing: `show_in_rest` false, meta not registered, or CPT lacks `custom-fields` support. |
| 111 | + |
| 112 | +## Escalation |
| 113 | + |
| 114 | +If version support or behavior is unclear, consult the REST API Handbook and core docs before inventing patterns. |
0 commit comments