REST API

NimblyMail exposes a single action hook that fires during rest_api_init after all core controllers are registered. A Pro add-on hooks here to register its own controllers using standard WordPress REST APIs. The free plugin places no constraints on the Pro namespace, route structure, or authentication scheme.

Registering a Pro REST Controller

Step 1 — Extend AbstractController

NimblyMailRestAbstractController enforces the manage_options capability check and provides a send_error() helper. Extending it is optional but recommended for consistency.

<?php

defined( 'ABSPATH' ) || exit;

use NimblyMailRestAbstractController;
use WP_REST_Request;
use WP_REST_Response;

/**
 * REST controller for Pro reporting endpoints.
 *
 * @since 1.0.0 Added Pro reporting endpoints.
 */
class NimblyMail_Pro_Reports_Controller extends AbstractController {

    /**
     * Register all routes for this controller.
     *
     * @since 1.0.0 Added Pro reporting endpoints.
     *
     * @return void
     */
    public function register_routes(): void {
        register_rest_route(
            'nimbly-mail-pro/v1',
            '/reports/generate',
            array(
                'methods'             => 'POST',
                'callback'            => array( $this, 'generate_report' ),
                'permission_callback' => array( $this, 'permissions_check' ),
                'args'                => array(
                    'date_from' => array(
                        'type'              => 'string',
                        'format'            => 'date',
                        'required'          => true,
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                    'date_to'   => array(
                        'type'              => 'string',
                        'format'            => 'date',
                        'required'          => true,
                        'sanitize_callback' => 'sanitize_text_field',
                    ),
                ),
            )
        );

        register_rest_route(
            'nimbly-mail-pro/v1',
            '/reports/bounce-rate',
            array(
                'methods'             => 'GET',
                'callback'            => array( $this, 'get_bounce_rate' ),
                'permission_callback' => array( $this, 'permissions_check' ),
            )
        );
    }

    /**
     * Generate a delivery report for the requested date range.
     *
     * @since 1.0.0 Added Pro reporting endpoints.
     *
     * @param WP_REST_Request $request The REST request object.
     *
     * @return WP_REST_Response The report data.
     */
    public function generate_report( WP_REST_Request $request ): WP_REST_Response {
        $from = $request->get_param( 'date_from' );
        $to   = $request->get_param( 'date_to' );

        // ... build report ...
        $report = array( 'rows' => array() );

        return new WP_REST_Response( $report, 200 );
    }

    /**
     * Return the 24-hour bounce rate stat.
     *
     * @since 1.0.0 Added Pro reporting endpoints.
     *
     * @param WP_REST_Request $request The REST request object.
     *
     * @return WP_REST_Response The bounce rate data.
     */
    public function get_bounce_rate( WP_REST_Request $request ): WP_REST_Response {
        return new WP_REST_Response(
            array(
                'value' => 1.4,
                'unit'  => '%',
                'trend' => 'down',
            ),
            200
        );
    }
}

Step 2 — Register via the action hook

Signature: do_action( 'nimbly_mail_register_rest_routes' )

Fires during rest_api_init immediately after NimblyMail’s own controllers are registered. No parameters are passed; use register_rest_route() directly.

@since 1.0.0

add_action(
    'nimbly_mail_register_rest_routes',
    function (): void {
        $controller = new NimblyMail_Pro_Reports_Controller();
        $controller->register_routes();
    }
);

Namespace Recommendation

Use your own namespace — nimbly-mail-pro/v1 is the recommended convention. Registering routes under nimbly-mail/v1 is not blocked by the free plugin, but doing so creates a maintenance hazard: a future NimblyMail update could register a conflicting route under the same path.

Permission Callback Warning

Every route MUST set a permission_callback. Using __return_true as the permission callback is a security vulnerability — it exposes the endpoint to unauthenticated requests from anywhere on the internet.

AbstractController::permissions_check() already enforces current_user_can( 'manage_options' ) and returns the appropriate WP_Error for unauthorized requests. Inherit it by passing array( $this, 'permissions_check' ) as shown above.

If your endpoint is intentionally public (for example, a webhook receiver), implement an explicit token-based or signature-based check in the permission_callback — do not use __return_true.

Was this article helpful?