I've got the following basic route for my custom REST endpoint: add_action('rest_api_init', 'my_cpt_route'); function my_cpt_route() { register_rest_route('mytheme/v1/', 'my_cpt', array( 'methods' => WP_REST_SERVER::READABLE, 'callback' => 'my_cpt_results', )); } And this is the CB function: function my_cpt_results() { $args = array( 'post_type' => array('my_cpt'), 'posts_per_page' => -1, ); $mainQuery = new WP_Query($args); $results = array(); while ($mainQuery->have_posts()) { $mainQuery->the_post(); array_push($results, array( 'id' => get_the_ID(), 'title' => get_the_title(), 'url' => get_the_permalink(), 'image' => array( 'small' => get_the_post_thumbnail_url(0, 'thumbnail'), 'medium' => get_the_post_thumbnail_url(0, 'medium'), 'large' => get_the_post_thumbnail_url(0, 'large'), ) )); $results = array_values(array_unique($results, SORT_REGULAR)); } wp_reset_postdata(); return $results; } This works just fine when I retrieve all the posts (so if I go to "http://mysite.test/wp-json/mytheme/v1/my_cpt/" I get all the CPT posts). What I expected is that if I append an id of a published CPT post at the end of the URL (eg.: "http://mysite.test/wp-json/mytheme/v1/my_cpt/56") I had to get only the post with id 56. Instead, I get a 404 "rest_no_route". Maybe I need to modify the register_rest_route args? (but how?)... UPDATE @moped...and how to get the same results using this functions as class methods? I'm not much into OOP and I'd like to learn... Say I've got the following simple class (based on wppb.me plugin boilerplate): class My_Routes { /** * The ID of this plugin. * * @since 1.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 1.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of this plugin. * @param string $version The version of this plugin. */ public function __construct($plugin_name, $version) { $this->plugin_name = $plugin_name; $this->version = $version; } /** * Creates routes */ public static function register_cpt_routes() { register_rest_route('mytheme/v1/', 'my_cpt', array( 'methods' => WP_REST_SERVER::READABLE, 'callback' => array( $this, 'get_posts' ), )); register_rest_route('mytheme/v1/', 'my_cpt/(?P<id>[\d]+)', array( 'methods' => WP_REST_SERVER::READABLE, 'callback' => array( $this, 'get_post' ), )); } /** * Callback function to load all posts */ public static function get_posts() { // ...do stuff for getting all the posts, and this is working } /** * Callback function to load a single post */ public static function get_post($data) { // How do I pass the $data args to the get_post method? $cpt_id = $data['id']; // ...do stuff } }