 Hey there, and welcome to Learn WordPress. In this tutorial, you're going to learn how to modify WordPress REST API responses. You will learn about two methods of adding fields to your REST API requests, either by enabling custom fields in the REST API route, or by making custom fields available as top-level fields. You'll also learn about the pros and cons to both approaches. For the purposes of this tutorial, you'll be using the Postman API testing tool to test your modified API requests. If you haven't done it already, download and install the Postman app for your operating system. Before we get started, it's important to note that modifying WordPress REST API responses can have unexpected consequences. Changing or removing data from core REST API endpoint responses can break plugins or WordPress core behavior, and should be avoided wherever possible. If you need to retrieve a subset of data from a REST API request, the recommended method is rather to use the fields global parameter to limit the fields returned in the response. For example, you can use the fields parameter to limit the fields returned to just ID, title, and excerpt, if those are the only fields you need for your application. So for example, here we have a standard get request to the post endpoint, and you can see in the response it returns all the fields. However, we just need a few fields, so we can use the fields parameter and specify ID, title, and excerpt. And when we process that request, only those fields will be returned. Adding fields to a REST API response is considered less risky, and so this tutorial only covers adding fields. In the custom fields and authentication tutorial, you learned how to take custom fields, also known as post meta, added using the register meta function to enable them for the WordPress REST API. To do this, you use the show in REST argument in the arguments array passed to the register meta function and set it to true. This will enable the custom field to be added to the REST API response, and will also allow you to post data to the custom field using the REST API. This is handled by passing the custom field as a key value pair in the meta object of the request body. So for example, if we had a post request configured to the posts route with the authorization already set to the application password, we could pass in a JSON body that looks like this, so it has a title, it has some content, it has a status, and then it has the meta object. And inside of the meta object, there is a URL property with a value. If we submit this request, the post is created and the URL custom field is stored in the meta object, and we can verify this by looking at the post and seeing the custom field stored on the post. This is also the most common way to enable custom fields on your WordPress REST API routes. As it allows you to make use of custom fields, you may have already registered using the register meta function. Prior to WordPress 4.9.8, custom fields set to show in REST using register meta were registered for all objects of a given type. For example, if you added a custom field to the posts type and then created a custom post type, the custom field would automatically be available on the custom post type. As of WordPress 4.9.8, it's possible to use register meta with the object subtype argument that allows one to reduce the usage of the meta key to a particular post type. For example, let's say in your plugin you have a URL custom field registered to the default post type. You then decide to register a new custom post type called book. By default, the URL custom field will be available on both posts and books. You then decide you want the URL custom field to only be available on the book custom post type. You can do this by passing the object subtype argument to the existing register meta function. So here we can say object subtype and set it to book. If you queried posts via the REST API, the URL meta field would no longer be visible. It would now only appear if you queried the books. You can register additional custom fields on a custom post type using the object subtype argument. For example, if you wanted to register a custom field called ISBN on the book custom post type. So for that, let's grab the register meta code and it's generally better to register your post meta after the post. And then we can use it again to do an ISBN and assign it to the object subtype book. You would now have both URL and ISBN custom fields available on the book custom post type. You can test this by adding a book via the REST API. So let's create a new request that will post to the book endpoint and we can copy out the URL, change the method to a post, use the basic authentication which has already been saved from previous requests and then set the body to passing some JSON and the object can look like this. So title new book content, new book content, status of publish and then pass in the URL and the ISBN in the meta object and let's send that request and the book has been created with the URL and ISBN custom field set. The other way to add custom fields to the REST API is to add them as top-level fields on REST API responses. In the earlier example, the ISBN was registered as a meta field and is therefore available in the meta object of the REST API response for the book. But what if you prefer to have it as a top-level field alongside things like title, content and excerpt? This can be achieved using the register REST field function. Let's look at how this would be implemented. First, you need to register your REST fields in the REST API init action hook. This is to ensure that the field is only registered on the REST API. So right at the top here, let's say add action. So REST API init is the hook and the function we'll use is WP learn REST API init. Then let's create that function and sets it up to start registering fields. You can then use the register REST field function to register the field. The first parameter is the object type the field should be registered on. This can be a string for a single object or an array for more than one object. In this case, just register the field on the book custom post type. The second argument is the name of the field. In this case, just make it the same as the custom field, ISBN. The third parameter is an array of arguments that determines how the field functions. You need to pass at least the following three arguments to this array. So the first is the get callback. This is a function that returns the value of the field. The second is the update callback. This is a function that updates the value of the field when a post request is made. And lastly, the schema. This is an array containing the schema for the field. For now, you can leave the schema argument of the REST field as null, but you will need to specify the get callback and update callback functions. These are the functions that will be triggered when an API request is made, either to fetch the data or to create or update the data. So for these two, we can just go something as simple as WP learn, REST get ISBN, and WP learn, REST update ISBN. Then we need to create these functions. So get ISBN and update ISBN. By default, an array of the post types prepared data is passed to the get callback function as the first argument. An implementation of this function could be as straightforward as returning the value of the custom field. So we can specify the book variable here to receive that prepared data and then do something as simple as return, get, post, meta, and then book ID. That's the ID of the book. And we want to return the ISBN meta property. And we need to pass in true for the third parameter because this is a single response. The value sent for the field from a REST API, create or update request is passed to the update callback function as the first argument, and the model object, i.e. the post as the second argument. So when we're working with the update function, we can pass in at least set up a value variable to receive the new value. In this case, we can set up book to receive the custom post type. An implementation of this function could be as simple as updating the value of the custom field. So we could do something like this. We could say return, update, post, meta, book. And because this is an object, we need to reference the ID using the object syntax, specify the custom field that we're updating, and pass in the new value. You can test this out by creating a new book and passing a value for the ISBN field. You'll see the data being saved to the database in the post meta table, but being displayed as a top-level field on the REST API response. So let's have a look at that. So here is our book request. So let's create... Let's use that to create a new book with some additional fields and pass in a slightly different set of data there and hit send. So the book has been created. You'll notice that it contains the meta object, which contains the URL and the ISBN, but the ISBN field is also duplicated in the top-level field. If we requested the books and we removed meta and specified ISBN, then we will receive the ISBN field because it is available as a registered field on the books. The schema argument of register REST field is an array that describes the schema for the field. While it's not a requirement, including a schema is encouraged. If nothing else, it helps future developers understand what the field is for. It can also be used to validate the data being sent when creating automated API tests. So your schema could be as simple as saying something like creating an array and then passing in a description. Let me say something like the ISBN number of the book and then we would also want to give it a type and we'll make it a string. You can read more about how to define the schema for REST API resources and fields in the WP REST API Handbook at developer.wordpress.org. The main advantage of using the register meta route is that you do not need to add any further code to enable storing or retrieving data from the custom fields as long as you remember to fetch and save the data using the meta object in your application code. You enable the field to show it in the REST API and you can use it straight away. This is also the more performance option as it does not add any additional code that needs to be executed. On the other hand, the main advantage of using the register REST field route is that the field appears as a top-level field in your REST API route. The other advantage is that you can perform additional processing on the data before it is returned or before it is saved. For example, you could perform some validation on the data before it is saved to the database. You could also add hooks to the get callback and update callback functions to either perform additional processing on the data or to allow other developers to extend your custom fields. The downside is that you're adding a slight overhead to the API requests as it adds more code that needs to be executed. Ultimately, the route you choose should be decided on a case-by-case basis. For more information on this, check out the Modifying Responses section of the WP REST API Handbook at developer.wordpress.org. Happy coding!