FSWP API Developer
Foundational (always applied): fswp-developer/references/lean-coding.md (write less, reuse first), fswp-developer/references/coding-standards.md (coding standards, docs, i18n, accessibility), and fswp-security-engineer (input, output, authorization).
Official reference: REST API Handbook (fswp-developer/references/official-docs.md). Security rules in fswp-security-engineer apply to every route.
Register a route
function vp_register_routes() {
register_rest_route( 'vendor-prefix/v1', '/items/(?P<id>\d+)', array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'vp_get_item',
'permission_callback' => function ( WP_REST_Request $r ) {
return current_user_can( 'edit_post', (int) $r['id'] );
},
'args' => array(
'id' => array( 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint' ),
),
) );
}
add_action( 'rest_api_init', 'vp_register_routes' );
Rules
- Namespace and version:
vendor-prefix/v1. Never register in core'swp/v2namespace. permission_callbackis mandatory. Return a capability check, not just login status. Use__return_trueonly for genuinely public data, with a comment explaining why. Check object-level access (edit_post, ownership) whenever an ID is in the request.- Declare
argswithtype,required,enum,minimum/maximum,validate_callback, andsanitize_callback. The request is untrusted even after validation; use$request->get_param()values as typed. - Return data with
rest_ensure_response(); errors asnew WP_Error( 'vp_code', __( 'Message', 'text-domain' ), array( 'status' => 404 ) ). Use accurate status codes (400 invalid, 401 unauthenticated, 403 forbidden, 404 missing, 409 conflict, 413 too large). - Schema: implement
get_item_schema()(orschemacallback) so clients and the index can describe the resource; shape responses withprepare_item_for_response(). - Collections: support
page/per_pagewith a hard cap, setX-WP-TotalandX-WP-TotalPages, and never return unbounded lists. - Never return secrets, password hashes, raw options, or other users' private data.
- Controllers: for more than a couple of routes, extend
WP_REST_Controller(register_routes,get_items,get_item,create_item, permission checks per method) and register the class once. - Expose core objects: custom post types and taxonomies with
'show_in_rest' => true(andrest_base); meta withregister_meta()/register_post_meta()and'show_in_rest' => trueplus a schema and anauth_callback. - Caching and performance: cheap
GEThandlers; cache expensive results (fswp-performance-engineer); avoid queries in loops.
Authentication
| Client | Method |
|---|---|
| Same-site JS (admin, blocks, front end) | Cookie auth with the X-WP-Nonce header (wp_create_nonce( 'wp_rest' ), or wp_localize_script / @wordpress/api-fetch which adds it) |
| External server or app | Application Passwords over HTTPS, or a vetted OAuth plugin |
| Public read | No auth, only when the data is public |
Nonces do not replace capability checks. CORS: do not open Access-Control-Allow-Origin: * on authenticated routes.
Client side
Use @wordpress/api-fetch in blocks and admin screens. Handle errors by code and message, not by parsing text.
Abilities API
A Core API for registering discrete, machine-readable capabilities (name, input schema, output schema, permission check, execute callback) that tools and AI agents can discover and call. It is recent: confirm the minimum WordPress version and the exact function names in the developer documentation before using it (search "Abilities API"). Use it only when the PRD needs agent-callable functions; plain REST is right for ordinary client-server calls.
When registering an ability:
- Register the category first, then the ability, on the documented hooks.
- Give it JSON Schemas for input and output, and a
permission_callbackthat checks a real capability. - Set the safety annotations honestly: read-only abilities must not write, destructive ones must be flagged. A callback that writes while annotated read-only is a defect, and
fswp-reviewertreats it as one. - Expose over REST only what should be callable remotely.
Audit and verification procedures: references/abilities.md.
To propose which existing endpoints should become abilities, list each route with its method, current permission check, side effects, and a suggested annotation; do not register anything until approved.