The Front Door You Forgot You Built: What These 5 REST API Hooks Actually Gate
The Problem Every WordPress install answers REST requests at /wp-json/ whether or not anyone deliberately built an API — and most sites have at least one custom field,…

Action Hook since 4.7.0
Fires after a post is created or updated through the REST API
rest_insert_post is the REST-specific counterpart to save_post — it fires inside the Posts controller with the actual REST request object available, which save_post alone doesn't give you.
Inside WP_REST_Posts_Controller, after the post is saved via the REST API — save_post also fires for the same request, but without direct access to the REST request object.
do_action( 'rest_insert_post', WP_Post $post, WP_REST_Request $request, bool $creating );post WP_Post — The post object that was inserted or updated.request WP_REST_Request — The REST request that triggered the insert.creating bool — True when a new post was created, false when an existing post was updated.add_action( 'rest_insert_post', function( $post, $request, $creating ) {
error_log( ( $creating ? 'Created' : 'Updated' ) . ' post via REST: ' . $post->ID );
}, 10, 3 );Log whether a REST call created or updated a post.
add_action( 'rest_insert_post', function( $post, $request, $creating ) {
$client_id = $request->get_header( 'X-Client-App' );
if ( $client_id ) {
update_post_meta( $post->ID, '_created_via', sanitize_text_field( $client_id ) );
}
}, 10, 3 );Tag posts with which headless client created them, using a custom request header.
add_action( 'rest_insert_post', function( $post, $request, $creating ) {
// save_post fires too for this same request —
// guard against running duplicate logic in both places.
}, 10, 3 );save_post and rest_insert_post both fire for the same REST-created post — avoid double-running side effects.

The Problem Every WordPress install answers REST requests at /wp-json/ whether or not anyone deliberately built an API — and most sites have at least one custom field,…
Only if you need the REST request object itself — headers, route, or client-specific data that save_post doesn't expose.
No — both fire. rest_insert_post adds the request context on top of what save_post already gives you.
Source: wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
One session: this hook, then each related_hooks entry. Walk it and tell us what to change.
rest_insert_post → save_post → rest_api_init
Practice the rest_insert_post WordPress action hook in our interactive sandbox — a VS Code-style editor with a step-by-step rest_insert_post tutorial, add_action exercises, and instant feedback. No local WordPress install required.