admin-ajax versus a rewrite endpoint

Every request to admin-ajax.php loads the full admin bootstrap before reaching your handler — a measurable amount of work for an endpoint that returns three fields, and it happens on the front end too.

add_action( 'init', function () {
    add_rewrite_rule( '^api/stock/([0-9]+)/?$', 'index.php?stock_id=$matches[1]', 'top' );
} );

add_filter( 'query_vars', function ( $vars ) {
    $vars[] = 'stock_id';
    return $vars;
} );

add_action( 'template_redirect', function () {
    $id = get_query_var( 'stock_id' );
    if ( $id ) {
        wp_send_json( array( 'in_stock' => stock_for( (int) $id ) ) );
    }
} );

The rewrite route skips the admin load entirely and gives a URL that can be cached by a proxy, which admin-ajax.php?action=... effectively cannot. It costs a rewrite flush on activation and a slightly less obvious registration. From 4.7 the REST API is the better answer again for anything with more than one endpoint.