Index: src/js/_enqueues/admin/site-health.js
===================================================================
--- src/js/_enqueues/admin/site-health.js	(revision 6bd7097626c15aa331b23ad0c9f1692c161deddb)
+++ src/js/_enqueues/admin/site-health.js	(date 1569207016981)
@@ -162,11 +162,20 @@
 
 		if ( 1 <= SiteHealth.site_status.async.length ) {
 			$.each( SiteHealth.site_status.async, function() {
+				var url = ajaxurl;
+				var active_test = this.test;
 				var data = {
-					'action': 'health-check-' + this.test.replace( '_', '-' ),
+					'action': 'health-check-' + active_test.replace( '_', '-' ),
 					'_wpnonce': SiteHealth.nonce.site_status
 				};
 
+				if ( "undefined" !== typeof( this.has_rest ) && this.has_rest ) {
+					url = SiteHealth.rest_base + this.test;
+					data = {
+						'_wpnonce': SiteHealth.nonce.rest_api
+					};
+				}
+
 				if ( this.completed ) {
 					return true;
 				}
@@ -176,13 +185,33 @@
 				this.completed = true;
 
 				$.post(
-					ajaxurl,
-					data,
-					function( response ) {
-						AppendIssue( response.data );
-						maybeRunNextAsyncTest();
-					}
-				);
+					url,
+					data
+				).done( function( response ) {
+					AppendIssue( response.data );
+				} ).fail( function( response ) {
+					var description = __( 'No details available' );
+
+					if ( "undefined" !== typeof( response.responseJSON ) && "undefined" !== typeof( response.responseJSON.message ) ) {
+						description = response.responseJSON.message;
+					}
+
+					var issue = {
+						'status': 'recommended',
+						'label': sprintf( __( 'Unavailable test: %s' ), active_test ),
+						'test': active_test.replace( /\//g, '-' ),
+						'badge': {
+							'color': 'blue',
+							'label': __( 'Failed test' )
+						},
+						'description': '<p>' + description + '</p>',
+						'actions': ''
+					};
+
+					AppendIssue( issue );
+				} ).always(function() {
+					maybeRunNextAsyncTest();
+				});
 
 				return false;
 			} );
@@ -211,21 +240,7 @@
 		}
 
 		if ( 0 < SiteHealth.site_status.async.length ) {
-			data = {
-				'action': 'health-check-' + SiteHealth.site_status.async[0].test.replace( '_', '-' ),
-				'_wpnonce': SiteHealth.nonce.site_status
-			};
-
-			SiteHealth.site_status.async[0].completed = true;
-
-			$.post(
-				ajaxurl,
-				data,
-				function( response ) {
-					AppendIssue( response.data );
-					maybeRunNextAsyncTest();
-				}
-			);
+			maybeRunNextAsyncTest();
 		} else {
 			RecalculateProgression();
 		}
Index: src/wp-settings.php
===================================================================
--- src/wp-settings.php	(revision 6bd7097626c15aa331b23ad0c9f1692c161deddb)
+++ src/wp-settings.php	(date 1569193790586)
@@ -248,6 +248,7 @@
 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-block-renderer-controller.php' );
 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-settings-controller.php' );
 require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-themes-controller.php' );
+require( ABSPATH . WPINC . '/rest-api/endpoints/class-wp-rest-site-health-controller.php' );
 require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-meta-fields.php' );
 require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-comment-meta-fields.php' );
 require( ABSPATH . WPINC . '/rest-api/fields/class-wp-rest-post-meta-fields.php' );
Index: src/wp-admin/site-health.php
===================================================================
--- src/wp-admin/site-health.php	(revision 6bd7097626c15aa331b23ad0c9f1692c161deddb)
+++ src/wp-admin/site-health.php	(date 1569206044714)
@@ -27,10 +27,7 @@
 	require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' );
 }
 
-$health_check_site_status = new WP_Site_Health();
-
-// Start by checking if this is a special request checking for the existence of certain filters.
-$health_check_site_status->check_wp_version_check_exists();
+new WP_Site_Health();
 
 require_once( ABSPATH . 'wp-admin/admin-header.php' );
 ?>
Index: src/wp-admin/includes/class-wp-site-health-auto-updates.php
===================================================================
--- src/wp-admin/includes/class-wp-site-health-auto-updates.php	(revision 6bd7097626c15aa331b23ad0c9f1692c161deddb)
+++ src/wp-admin/includes/class-wp-site-health-auto-updates.php	(date 1569206880384)
@@ -86,46 +86,7 @@
 	 * @return array The test results.
 	 */
 	public function test_wp_version_check_attached() {
-		if ( ! is_main_site() ) {
-			return;
-		}
-
-		$cookies = wp_unslash( $_COOKIE );
-		$timeout = 10;
-		$headers = array(
-			'Cache-Control' => 'no-cache',
-		);
-		/** This filter is documented in wp-includes/class-wp-http-streams.php */
-		$sslverify = apply_filters( 'https_local_ssl_verify', false );
-
-		// Include Basic auth in loopback requests.
-		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
-			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
-		}
-
-		$url = add_query_arg(
-			array(
-				'health-check-test-wp_version_check' => true,
-			),
-			admin_url( 'site-health.php' )
-		);
-
-		$test = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );
-
-		if ( is_wp_error( $test ) ) {
-			return array(
-				'description' => sprintf(
-					/* translators: %s: Name of the filter used. */
-					__( 'Could not confirm that the %s filter is available.' ),
-					'<code>wp_version_check()</code>'
-				),
-				'severity'    => 'warning',
-			);
-		}
-
-		$response = wp_remote_retrieve_body( $test );
-
-		if ( 'yes' !== $response ) {
+		if ( ! has_filter( 'wp_version_check', 'wp_version_check' ) ) {
 			return array(
 				'description' => sprintf(
 					/* translators: %s: Name of the filter used. */
@@ -282,6 +243,11 @@
 	 * @return array The test results.
 	 */
 	function test_check_wp_filesystem_method() {
+		// Make sure the `request_filesystem_credentials` function is available during our REST call.
+		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
+			require_once( ABSPATH . '/wp-admin/includes/file.php' );
+		}
+
 		$skin    = new Automatic_Upgrader_Skin;
 		$success = $skin->request_filesystem_credentials( false, ABSPATH );
 
@@ -328,6 +294,11 @@
 			return false;
 		}
 
+		// Make sure the `get_core_checksums` function is available during our REST call.
+		if ( ! function_exists( 'get_core_checksums' ) ) {
+			require_once( ABSPATH . '/wp-admin/includes/update.php' );
+		}
+
 		$checksums = get_core_checksums( $wp_version, 'en_US' );
 		$dev       = ( false !== strpos( $wp_version, '-' ) );
 		// Get the last stable version's files and test against that
Index: src/wp-admin/includes/class-wp-site-health.php
===================================================================
--- src/wp-admin/includes/class-wp-site-health.php	(revision 6bd7097626c15aa331b23ad0c9f1692c161deddb)
+++ src/wp-admin/includes/class-wp-site-health.php	(date 1569205429878)
@@ -57,7 +57,9 @@
 
 		$health_check_js_variables = array(
 			'screen'      => $screen->id,
+			'rest_base'   => rest_url( '/' ),
 			'nonce'       => array(
+				'rest_api'           => wp_create_nonce( 'wp_rest' ),
 				'site_status'        => wp_create_nonce( 'health-check-site-status' ),
 				'site_status_result' => wp_create_nonce( 'health-check-site-status-result' ),
 			),
@@ -110,6 +112,7 @@
 				if ( is_string( $test['test'] ) ) {
 					$health_check_js_variables['site_status']['async'][] = array(
 						'test'      => $test['test'],
+						'has_rest'  => ( isset( $test['has_rest'] ) ? $test['has_rest'] : false ),
 						'completed' => false,
 					);
 				}
@@ -1816,16 +1819,19 @@
 			),
 			'async'  => array(
 				'dotorg_communication' => array(
-					'label' => __( 'Communication with WordPress.org' ),
-					'test'  => 'dotorg_communication',
+					'label'    => __( 'Communication with WordPress.org' ),
+					'test'     => 'wp/v2/site-health/test-dotorg-communication',
+					'has_rest' => true,
 				),
 				'background_updates'   => array(
-					'label' => __( 'Background updates' ),
-					'test'  => 'background_updates',
+					'label'    => __( 'Background updates' ),
+					'test'     => 'wp/v2/site-health/test-background-updates',
+					'has_rest' => true,
 				),
 				'loopback_requests'    => array(
-					'label' => __( 'Loopback request' ),
-					'test'  => 'loopback_requests',
+					'label'    => __( 'Loopback request' ),
+					'test'     => 'wp/v2/site-health/test-loopback-requests',
+					'has_rest' => true,
 				),
 			),
 		);
@@ -1884,6 +1890,11 @@
 	 * @return string The modified body class string.
 	 */
 	public function admin_body_class( $body_class ) {
+		$screen = get_current_screen();
+		if ( 'site-health' !== $screen->id ) {
+			return $body_class;
+		}
+
 		$body_class .= ' site-health';
 
 		return $body_class;
Index: src/wp-includes/rest-api/endpoints/class-wp-rest-site-health-controller.php
===================================================================
--- src/wp-includes/rest-api/endpoints/class-wp-rest-site-health-controller.php	(date 1569205295250)
+++ src/wp-includes/rest-api/endpoints/class-wp-rest-site-health-controller.php	(date 1569205295250)
@@ -0,0 +1,136 @@
+<?php
+/**
+ * REST API: WP_REST_Site_Health_Controller class
+ *
+ * @package WordPress
+ * @subpackage REST_API
+ * @since 5.3.0
+ */
+
+/**
+ * Core class for interacting with Site Health elements.
+ *
+ * @since 5.3.0
+ *
+ * @see WP_REST_Controller
+ */
+class WP_REST_Site_Health_Controller extends WP_REST_Controller {
+
+	private $site_health;
+
+	/**
+	 * Constructor.
+	 */
+	public function __construct() {
+		if ( ! class_exists( 'WP_Site_Health' ) ) {
+			require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' );
+		}
+
+		$this->site_health = new WP_Site_Health();
+
+		$this->namespace = 'wp/v2';
+		$this->rest_base = 'site-health';
+	}
+
+	/**
+	 * Register API routes.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @see register_rest_route()
+	 */
+	public function register_routes() {
+		register_rest_route(
+			$this->namespace,
+			sprintf(
+				'/%s/%s',
+				$this->rest_base,
+				'test-background-updates'
+			),
+			array(
+				'methods'             => 'POST',
+				'callback'            => array( $this, 'test_background_updates' ),
+				'permission_callback' => function() {
+					return $this->validate_request_permission( 'test-background-updates' );
+				},
+			)
+		);
+
+		register_rest_route(
+			$this->namespace,
+			sprintf(
+				'/%s/%s',
+				$this->rest_base,
+				'test-loopback-requests'
+			),
+			array(
+				'methods'             => 'POST',
+				'callback'            => array( $this, 'test_loopback_requests' ),
+				'permission_callback' => function() {
+					return $this->validate_request_permission( 'test-dotorg-communication' );
+				},
+			)
+		);
+
+		register_rest_route(
+			$this->namespace,
+			sprintf(
+				'/%s/%s',
+				$this->rest_base,
+				'test-dotorg-communication'
+			),
+			array(
+				'methods'             => 'POST',
+				'callback'            => array( $this, 'test_dotorg_communication' ),
+				'permission_callback' => function() {
+					return $this->validate_request_permission( 'test-dotorg-communication' );
+				},
+			)
+		);
+	}
+
+	public function validate_request_permission( $check ) {
+		$capability = apply_filters( "site_health_test_rest_capability_{$check}", 'view_site_health_checks', $check );
+
+		return current_user_can( $capability );
+	}
+
+	/**
+	 * Check if background updates work as expected.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @return array
+	 */
+	public function test_background_updates() {
+		return array(
+			'data' => $this->site_health->get_test_background_updates()
+		);
+	}
+
+	/**
+	 * Check that the site can reach the WordPress.org API.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @return array
+	 */
+	public function test_dotorg_communication() {
+		return array(
+			'data' => $this->site_health->get_test_dotorg_communication()
+		);
+	}
+
+	/**
+	 * Check that loopbacks can be performed.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @return array
+	 */
+	public function test_loopback_requests() {
+		return array(
+			'data' => $this->site_health->get_test_loopback_requests()
+		);
+	}
+}
Index: src/wp-includes/rest-api.php
===================================================================
--- src/wp-includes/rest-api.php	(revision 6bd7097626c15aa331b23ad0c9f1692c161deddb)
+++ src/wp-includes/rest-api.php	(date 1569194174576)
@@ -272,6 +272,10 @@
 	$controller = new WP_REST_Settings_Controller;
 	$controller->register_routes();
 
+	// Site Health
+	$controller = new WP_REST_Site_Health_Controller;
+	$controller->register_routes();
+
 	// Themes.
 	$controller = new WP_REST_Themes_Controller;
 	$controller->register_routes();
