keepcalculator

06 Numbers and Powers

Create a Custom WordPress REST API Endpoint

Card No. 06·58499 · Updated · Standard formula, shown below

A custom WordPress REST API endpoint lets a plugin or theme expose data or actions through a URL, so another application can request or update information in a consistent way. You’ll register a route in PHP, define what it accepts and returns, and choose whether requests are public or require permission. Before starting, use a test site or backup, and have access to a child theme or plugin where you can safely add code.

What You’ll Need

  • A WordPress site with permission to edit or install code. A small site-specific plugin is usually safer than putting endpoint code in a theme.
  • A code editor and a way to upload or deploy PHP changes, such as your hosting file manager, SFTP, or a development workflow.
  • The endpoint’s purpose, HTTP method, expected request fields, response format, and access rules.
  • A REST client such as curl or an API testing tool, plus a staging site if available.

Step-by-Step

  1. Choose a namespace and route. WordPress REST URLs include a namespace and route, for example /wp-json/acme/v1/status. Use a namespace that identifies your project and a version such as v1. Avoid generic names that may collide with another plugin. The namespace is part of the public API, so changing it later can break clients.
  2. Put the code in a site-specific plugin. Create a directory such as wp-content/plugins/acme-api and add acme-api.php. Add a plugin header at the top of the PHP file, then place the registration code below it. Activate the plugin in the WordPress admin. This keeps the endpoint available if you change themes. For a quick test, a child theme can work, but avoid editing a parent theme or WordPress core.
  3. Register the route on the REST API initialization hook. Add this example to the plugin file:
    <?php
    /**
     * Plugin Name: Acme Custom API
     */
    add_action( 'rest_api_init', function () {
        register_rest_route( 'acme/v1', '/status', array(
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => 'acme_get_status',
            'permission_callback' => '__return_true',
        ) );
    } );
    
    function acme_get_status( WP_REST_Request $request ) {
        return rest_ensure_response( array(
            'status' => 'ok',
        ) );
    }

    The hook ensures registration happens when WordPress prepares its REST routes. READABLE means a GET request. The callback returns data, and rest_ensure_response() turns it into a REST response. This example is deliberately public and read-only; do not copy its public permission setting for a route that changes data or reveals private information.

  4. Define permissions deliberately. Every custom route should have a permission_callback. For public, non-sensitive information, __return_true may be appropriate. For a private route, check the current user’s capability, for example current_user_can( 'edit_posts' ), and return false or a WP_Error when access is denied. Use capabilities that match the action, not a role name. Cookie-authenticated requests from logged-in users generally need a WordPress REST nonce; application passwords or another supported authentication method may suit external clients. Authentication and authorization are separate: verify who is calling, then check what they may do.
  5. Add and validate request arguments. For input, declare an args array in the route definition. Each argument can specify a sanitize_callback, a validate_callback, and whether it is required. For example, a numeric record ID might use absint to sanitize and a validation callback that rejects zero. Sanitizing changes input into an acceptable form; validation decides whether it is allowed. Validate values again against the needs of the operation, and never assume data is safe because it came from an API client.
  6. Return a useful response or error. Return a simple array or a WP_REST_Response for success. For expected failures, return a WP_Error with a stable error code, a readable message, and an appropriate HTTP status, such as 400 for invalid input or 404 for a missing record. Do not expose database details, file paths, credentials, or stack traces. Keep response fields consistent so clients can rely on them.
  7. Test the route. Activate the plugin, then send a GET request to https://example.com/wp-json/acme/v1/status, replacing the domain with your site. For example: curl -i https://example.com/wp-json/acme/v1/status. Confirm the HTTP status and JSON body. Also test an invalid argument and, for a protected route, a request without permission and one with the correct authentication. Check both the site’s normal and pretty-permalink REST URL behavior if you suspect rewrite issues.
  8. Deploy and document it. Test on staging before production. Record the URL, method, required fields, authentication requirements, possible response fields, and error behavior. If you change the response shape or route, consider a new namespace version rather than silently breaking existing clients.

Common Mistakes

  • Omitting the permission callback: WordPress expects one. Choose an explicit public policy or a capability check rather than leaving access unclear.
  • Making a write route public: A public endpoint that creates, updates, or deletes data can be abused. Require suitable authentication and authorization, validate input, and consider rate limits for resource-intensive actions.
  • Using the wrong hook or route format: Register routes inside rest_api_init, and include a namespace and a route beginning with a slash.
  • Trusting request data: Sanitize and validate every field, check ownership where relevant, and use WordPress APIs for database operations rather than building unsafe SQL.
  • Editing the wrong file: Parent-theme changes can disappear on updates. A small plugin is easier to maintain and keeps API behavior independent of the display theme.

Tips

  • Use WordPress REST constants such as WP_REST_Server::READABLE and WP_REST_Server::CREATABLE to make the intended HTTP method clear.
  • Keep callbacks focused: read or update the needed data, then return a predictable response. Move larger operations into named helper functions.
  • For a public endpoint, expose only fields intended for public access. Do not return full user or database objects by default.
  • Test permissions and invalid input as carefully as the successful request. A route that works for an administrator may fail for ordinary users—or accidentally grant them access.

Troubleshooting

  • 404 or “rest_no_route”: Check the namespace, route spelling, HTTP method, and plugin activation. Visit /wp-json/ to see whether the REST API is reachable. If pretty permalinks are disabled or rewrite rules are stale, save the Permalinks settings in WordPress and test again.
  • PHP error or blank response: Check the PHP error log and WordPress debug log if logging is enabled. Look for missing brackets, misspelled function names, or code placed outside the plugin file’s PHP block. Fix errors on staging before deploying.
  • 401 or 403 response: Confirm the route’s permission callback, the authenticated user’s capability, and the authentication method. For cookie authentication, send a valid REST nonce. Do not make the route public merely to bypass an authorization problem.
  • 400 response or rejected field: Compare the request parameter names and types with the route’s argument definitions. Check validation rules and send valid JSON with the correct content type when using a JSON request body.
  • Unexpected output or wrong status: Inspect the callback’s returned value and any PHP notices or warnings. Return a response or WP_Error rather than printing output directly, then retest with response headers visible.

Frequently Asked Questions

Do I need to create a database table?
No. An endpoint can return existing WordPress data or calculated values. Create custom storage only when the feature genuinely needs it.

Can I add an endpoint without a plugin?
Yes, code in a child theme can register one, but it will stop loading if that theme is changed. A site-specific plugin is usually more reliable.

How do I make an endpoint require a logged-in user?
Use a permission callback that checks an appropriate capability. The client must also authenticate; cookie-based REST requests typically require a valid nonce.

Can the endpoint accept POST requests?
Yes. Set the route’s method to a suitable constant, such as WP_REST_Server::CREATABLE, then validate the request and enforce permissions before changing data.

How can I see the available routes?
Visit https://your-site.example/wp-json/ in a browser or API client. The index lists routes that WordPress exposes, subject to access and site configuration.

Should I version my endpoint?
Usually. A namespace such as acme/v1 makes later changes easier to introduce without unexpectedly breaking clients using the existing response format.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →