diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
index 42ceec93d8..3465271a11 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
@@ -1575,6 +1575,23 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 			}
 		}
 
+		$post_type_obj = get_post_type_object( $post->post_type );
+		if ( is_post_type_viewable( $post_type_obj ) && $post_type_obj->public  ) {
+
+			if ( ! function_exists( 'get_sample_permalink' ) ) {
+				require_once ABSPATH . '/wp-admin/includes/post.php';
+			}
+
+			$sample_permalink = get_sample_permalink( $post->ID, $post->post_title, '' );
+
+			if ( in_array( 'permalink_template', $fields, true ) ) {
+				$data['permalink_template'] = $sample_permalink[0];
+			}
+			if ( in_array( 'generated_slug', $fields, true ) ) {
+				$data['generated_slug'] = $sample_permalink[1];
+			}
+		}
+
 		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
 		$data    = $this->add_additional_fields_to_object( $data, $request );
 		$data    = $this->filter_response_by_context( $data, $context );
@@ -1907,6 +1924,21 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 		);
 
 		$post_type_obj = get_post_type_object( $this->post_type );
+		if ( is_post_type_viewable( $post_type_obj ) && $post_type_obj->public ) {
+			$schema['properties']['permalink_template'] = array(
+				'description' => __( 'Permalink template for the object.' ),
+				'type'        => 'string',
+				'context'     => array( 'edit' ),
+				'readonly'    => true,
+			);
+
+			$schema['properties']['generated_slug'] = array(
+				'description' => __( 'Slug automatically generated from the object title.' ),
+				'type'        => 'string',
+				'context'     => array( 'edit' ),
+				'readonly'    => true,
+			);
+		}
 
 		if ( $post_type_obj->hierarchical ) {
 			$schema['properties']['parent'] = array(
diff --git a/tests/phpunit/includes/testcase-rest-controller.php b/tests/phpunit/includes/testcase-rest-controller.php
index 04e1cf2f96..3087bcd7b7 100644
--- a/tests/phpunit/includes/testcase-rest-controller.php
+++ b/tests/phpunit/includes/testcase-rest-controller.php
@@ -40,7 +40,7 @@ abstract class WP_Test_REST_Controller_Testcase extends WP_Test_REST_TestCase {
 	abstract public function test_get_item_schema();
 
 	public function filter_rest_url_for_leading_slash( $url, $path ) {
-		if ( is_multisite() ) {
+		if ( is_multisite() || get_option( 'permalink_structure' ) ) {
 			return $url;
 		}
 
diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php
index d17dfdf20b..a5ca6b8c74 100644
--- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php
@@ -1114,7 +1114,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
 		$response = $this->server->dispatch( $request );
 		$data = $response->get_data();
 		$properties = $data['schema']['properties'];
-		$this->assertEquals( 24, count( $properties ) );
+		$this->assertEquals( 26, count( $properties ) );
 		$this->assertArrayHasKey( 'author', $properties );
 		$this->assertArrayHasKey( 'alt_text', $properties );
 		$this->assertArrayHasKey( 'caption', $properties );
@@ -1126,6 +1126,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
 		$this->assertArrayHasKey( 'comment_status', $properties );
 		$this->assertArrayHasKey( 'date', $properties );
 		$this->assertArrayHasKey( 'date_gmt', $properties );
+		$this->assertArrayHasKey( 'generated_slug', $properties );
 		$this->assertArrayHasKey( 'guid', $properties );
 		$this->assertArrayHasKey( 'id', $properties );
 		$this->assertArrayHasKey( 'link', $properties );
@@ -1137,6 +1138,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
 		$this->assertArrayHasKey( 'modified_gmt', $properties );
 		$this->assertArrayHasKey( 'post', $properties );
 		$this->assertArrayHasKey( 'ping_status', $properties );
+		$this->assertArrayHasKey( 'permalink_template', $properties );
 		$this->assertArrayHasKey( 'status', $properties );
 		$this->assertArrayHasKey( 'slug', $properties );
 		$this->assertArrayHasKey( 'source_url', $properties );
diff --git a/tests/phpunit/tests/rest-api/rest-pages-controller.php b/tests/phpunit/tests/rest-api/rest-pages-controller.php
index 6df9d968dc..0b02ad138b 100644
--- a/tests/phpunit/tests/rest-api/rest-pages-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-pages-controller.php
@@ -525,12 +525,13 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$response = $this->server->dispatch( $request );
 		$data = $response->get_data();
 		$properties = $data['schema']['properties'];
-		$this->assertEquals( 22, count( $properties ) );
+		$this->assertEquals( 24, count( $properties ) );
 		$this->assertArrayHasKey( 'author', $properties );
 		$this->assertArrayHasKey( 'comment_status', $properties );
 		$this->assertArrayHasKey( 'content', $properties );
 		$this->assertArrayHasKey( 'date', $properties );
 		$this->assertArrayHasKey( 'date_gmt', $properties );
+		$this->assertArrayHasKey( 'generated_slug', $properties );
 		$this->assertArrayHasKey( 'guid', $properties );
 		$this->assertArrayHasKey( 'excerpt', $properties );
 		$this->assertArrayHasKey( 'featured_media', $properties );
@@ -542,6 +543,7 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$this->assertArrayHasKey( 'modified_gmt', $properties );
 		$this->assertArrayHasKey( 'parent', $properties );
 		$this->assertArrayHasKey( 'password', $properties );
+		$this->assertArrayHasKey( 'permalink_template', $properties );
 		$this->assertArrayHasKey( 'ping_status', $properties );
 		$this->assertArrayHasKey( 'slug', $properties );
 		$this->assertArrayHasKey( 'status', $properties );
diff --git a/tests/phpunit/tests/rest-api/rest-posts-controller.php b/tests/phpunit/tests/rest-api/rest-posts-controller.php
index ec38bd7a85..a51fa59d13 100644
--- a/tests/phpunit/tests/rest-api/rest-posts-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-posts-controller.php
@@ -3094,7 +3094,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$response = $this->server->dispatch( $request );
 		$data = $response->get_data();
 		$properties = $data['schema']['properties'];
-		$this->assertEquals( 24, count( $properties ) );
+		$this->assertEquals( 26, count( $properties ) );
 		$this->assertArrayHasKey( 'author', $properties );
 		$this->assertArrayHasKey( 'comment_status', $properties );
 		$this->assertArrayHasKey( 'content', $properties );
@@ -3102,6 +3102,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$this->assertArrayHasKey( 'date_gmt', $properties );
 		$this->assertArrayHasKey( 'excerpt', $properties );
 		$this->assertArrayHasKey( 'featured_media', $properties );
+		$this->assertArrayHasKey( 'generated_slug', $properties );
 		$this->assertArrayHasKey( 'guid', $properties );
 		$this->assertArrayHasKey( 'format', $properties );
 		$this->assertArrayHasKey( 'id', $properties );
@@ -3110,6 +3111,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$this->assertArrayHasKey( 'modified', $properties );
 		$this->assertArrayHasKey( 'modified_gmt', $properties );
 		$this->assertArrayHasKey( 'password', $properties );
+		$this->assertArrayHasKey( 'permalink_template', $properties );
 		$this->assertArrayHasKey( 'ping_status', $properties );
 		$this->assertArrayHasKey( 'slug', $properties );
 		$this->assertArrayHasKey( 'status', $properties );
@@ -3179,6 +3181,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 			'excerpt',
 			'featured_media',
 			'format',
+			'generated_slug',
 			'guid',
 			'id',
 			'link',
@@ -3186,6 +3189,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 			'modified',
 			'modified_gmt',
 			'password',
+			'permalink_template',
 			'ping_status',
 			'slug',
 			'status',
@@ -3684,7 +3688,76 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
 		$this->assertArrayNotHasKey( 'https://api.w.org/action-unfiltered-html', $links );
 	}
 
+	public function test_generated_permalink_template_generated_slug_for_non_viewable_posts() {
+		register_post_type(
+			'private-post',
+			array(
+				'label'              => 'Private Posts',
+				'supports'           => array( 'title', 'editor', 'author' ),
+				'show_in_rest'       => true,
+				'publicly_queryable' => false,
+				'public'             => true,
+				'rest_base'          => 'private-post',
+			)
+		);
+		create_initial_rest_routes();
+
+		wp_set_current_user( self::$editor_id );
+
+		$post_id = $this->factory->post->create(
+			array(
+				'post_title'  => 'Permalink Template',
+				'post_type'   => 'private-post',
+				'post_status' => 'draft',
+			)
+		);
+
+		// Neither 'permalink_template' and 'generated_slug' are expected for this post type.
+		$request = new WP_REST_Request( 'GET', '/wp/v2/private-post/' . $post_id );
+		$request->set_param( 'context', 'edit' );
+		$response = rest_get_server()->dispatch( $request );
+		$data     = $response->get_data();
+		$this->assertEquals( 200, $response->get_status() );
+		$this->assertArrayNotHasKey( 'permalink_template', $data );
+		$this->assertArrayNotHasKey( 'generated_slug', $data );
+	}
+
+	public function test_generated_permalink_template_generated_slug_for_posts() {
+		$this->set_permalink_structure( '/%postname%/' );
+		$expected_permalink_template = trailingslashit( home_url( '/%postname%/' ) );
+
+		wp_set_current_user( self::$editor_id );
+
+		$post_id = $this->factory->post->create(
+			array(
+				'post_title'  => 'Permalink Template',
+				'post_type'   => 'post',
+				'post_status' => 'draft',
+			)
+		);
+
+		// Both 'permalink_template' and 'generated_slug' are expected for context=edit.
+		$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id );
+		$request->set_param( 'context', 'edit' );
+		$response = rest_get_server()->dispatch( $request );
+		$data     = $response->get_data();
+		$this->assertEquals( 200, $response->get_status() );
+		$this->assertEquals( $expected_permalink_template, $data['permalink_template'] );
+		$this->assertEquals( 'permalink-template', $data['generated_slug'] );
+
+		// Neither 'permalink_template' and 'generated_slug' are expected for context=view.
+		$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id );
+		$request->set_param( 'context', 'view' );
+		$response = rest_get_server()->dispatch( $request );
+		$data     = $response->get_data();
+		$this->assertEquals( 200, $response->get_status() );
+		$this->assertArrayNotHasKey( 'permalink_template', $data );
+		$this->assertArrayNotHasKey( 'generated_slug', $data );
+
+	}
+
 	public function tearDown() {
+		_unregister_post_type( 'private-post' );
 		_unregister_post_type( 'youseeeme' );
 		if ( isset( $this->attachment_id ) ) {
 			$this->remove_added_uploads();
