How To Create A Custom Rest Api Endpoint In WordPress
The WordPress REST API lets you create your own URLs that return JSON. They are useful for mobile apps, JavaScript widgets and connecting external services. Register routes with register_rest_route() on the rest_api_init hook.
A public GET endpoint
function lotgrafix_register_routes() {
register_rest_route( 'lotgrafix/v1', '/posts', array(
'methods' => 'GET',
'callback' => 'lotgrafix_rest_posts',
'permission_callback' => '__return_true',
'args' => array(
'count' => array(
'default' => 5,
'sanitize_callback' => 'absint',
),
),
) );
}
add_action( 'rest_api_init', 'lotgrafix_register_routes' );
function lotgrafix_rest_posts( WP_REST_Request $request ) {
$lotgrafix_posts = get_posts( array(
'numberposts' => $request->get_param( 'count' ),
) );
$data = array();
foreach ( $lotgrafix_posts as $lotgrafix_post ) {
$data[] = array(
'id' => $lotgrafix_post->ID,
'title' => get_the_title( $lotgrafix_post ),
'link' => get_permalink( $lotgrafix_post ),
);
}
return rest_ensure_response( $data );
}
Test it at /wp-json/lotgrafix/v1/posts?count=3
A protected POST endpoint
function lotgrafix_register_save_route() {
register_rest_route( 'lotgrafix/v1', '/note', array(
'methods' => 'POST',
'callback' => 'lotgrafix_rest_save_note',
'permission_callback' => 'lotgrafix_rest_can_edit',
) );
}
add_action( 'rest_api_init', 'lotgrafix_register_save_route' );
function lotgrafix_rest_can_edit() {
return current_user_can( 'edit_posts' );
}
function lotgrafix_rest_save_note( WP_REST_Request $request ) {
$note = sanitize_text_field( $request->get_param( 'note' ) );
update_option( 'lotgrafix_note', $note );
return new WP_REST_Response( array( 'saved' => true ), 201 );
}
Rules to remember
permission_callbackis required. Use__return_trueonly for data that is fully public.- Use a unique namespace with a version, like
lotgrafix/v1. - Sanitize all input and return errors with
WP_Error. - For logged in requests from JavaScript, send the
X-WP-Nonceheader. See the post about using the REST API with fetch.
November 3, 2026


