Does WP REST API cache internally executed (rest_do_request) requests?

Does WP REST API cache internally executed requests?

No it does not, not out of the box. CDNs and caching plugins can and do interfere however, especially for unauthenticated REST requests.

As an example to demonstrate this with hard results and test my own conclusion I added a random number generator to my site:

https://tomjn.com/wp-json/tomjn/v1/random

This is the code:

function tomjn_rest_random() {
        return rand(1,100);
}       

add_action( 'rest_api_init', function () {
    register_rest_route( 'tomjn/v1', '/random/', [
        'methods' => 'GET',
        'permission_callback' => '__return_true',
        'callback' => 'tomjn_rest_random',
        'show_in_index' => false,
    ] );
} );

This includes rest_do_request, WordPress has no page/response level caching built in, these are all provided by 3rd party services/software.

Note though that WP does cache some functions if a dedicated object cache is present, but never anything as large as an entire REST API response. This is on the scale of individual posts/terms/meta fetched from the database, or expensive calls such as figuring out post counts for a category, smaller atomic pieces of data that aren’t enough to explain your results.

A Note on HTTP request/response cache headers

no-cache does not do what you think it does! It means cache the result, but mandates that a request must be made to validate that it’s still current. So unless you’ve implemented etags etc the browser might not realise the response has changed, especially since this isn’t a static file.

From MDN:

The no-cache response directive indicates that the response can be stored in caches, but the response must be validated with the origin server before each reuse, even when the cache is disconnected from the origin server.

If you want caches to always check for content updates while reusing stored content, no-cache is the directive to use. It does this by requiring caches to revalidate each request with the origin server.

Note that no-cache does not mean “don’t cache”. no-cache allows caches to store a response but requires them to revalidate it before reuse. If the sense of “don’t cache” that you want is actually “don’t store”, then no-store is the directive to use.

Instead consider using no-store:

The no-store response directive indicates that any caches of any kind (private or shared) should not store this response.

Further reading: