 All right, so welcome to old WordPress REST API and new tricks, how to create a custom REST API point and make cool stuff. So I'm just going to talk about myself for a little second. So just to let you know, I am self-taught. I've always had a knack for figuring things out. I don't really have any formal training in computer sciences, but I have lots of hands-on experience. I've worked with WordPress for about 10 years. I've been with the agency for about six, and I work with a great collaborative team. I'm also on the WordPress documentation team. I recently joined in WordCamp Athens this year. Anybody can contribute and you don't need to know anything about programming to join the documentation team if you want to contribute to WordPress. And also this is my first talk at WordCamp. So I'll happily chat and answer any questions that you may have. I kind of knew it this, but anyways, here we go. So what we're going to be talking about today is I'm going to do a little bit of an introduction, what a REST API actually is, what comes in WordPress itself out of the box API endpoints. Then I'm going to walk through how to build your own custom endpoint. It's a lot easier than you would think. And then a little notes about security, and then finally a question and answer period. So what is the REST API? So WordPress introduced the REST API in version 4.7, which is in 2016. That's what makes it, quote unquote, old. And it became the foundation for the WordPress block editor, i.e., WordPress Gutenberg, and now with full site editing as well. So the REST API sends and receives data in JSON format, making it easy to integrate into web applications. JSON is very easy to read most applications, understand it, communicate with it. So you're already going to have to deal with XML or anything like that. So with the REST API, it's possible to completely rebuild WordPress. If you wanted to, you can create a new admin experience. You can completely create a new front-end experience. You can also create entirely new web applications based on your WordPress content. The REST API is actually only one of many WordPress APIs, and they're listed in the WordPress Codex. But today I'm only talking about the REST API. So what is a REST API? So it's Reparizational State Transfer Application Programming Interface. It's kind of a mouthful, but all it basically means is that it's a software architecture, meaning that you're going to get exactly sort of the same thing every time you hit an endpoint effectively. So what is an endpoint? So here I've broken down WordPress's endpoints and what they would look like. So HTTPS is the protocol, and you have the domain, which we're all familiar with. The wp-json is the base WordPress root for the API. Then you have the namespace, and the namespace varies. If it's coming from a plug-in, it's going to have a namespace. Later, when we create our own, we're actually going to define our namespace. The version of that API, and then finally the rest of the route. And then you could also do things like add query parameters on the end. So all REST APIs, not just WordPress, have four methods. We've got get, post, put, and delete. And what that means is that, well, get means you just get information, and that's what I'm going to be stepping through today. Post is you create a new entry into the database, put is you update or edit one, and delete is deleted. You just get rid of it. And your HTTP headers, you can add more information. So you can send more data along with it. That's pretty much a requirement if you're posting. And you also have parameters, so you can also filter your posts. So like in our example endpoint here, where we have posts, question mark, sticky equals true. That last part is the query parameter, and that's saying, OK, get all the posts, but we only want the sticky ones, as an example. All right, so what does WordPress come with? So WordPress already has built-in out of the box, baked in a bunch of API endpoints already. And you can get the full list in the developer handbook. So that's developerwordpress.org. Slash rest API, you can get all of it. So in WordPress, baked in, we've got posts, media, users, tags, pages, comments, taxonomies, post types, post statuses, and general blog settings. And you can get all that information right out of WordPress without installing a new plugin or doing anything. It's all right there. So APIs are, in fact, not intended for humans to quote unquote read. It's so that systems can talk to each other. That aren't really meant for a human to just hit an endpoint and then let's read what's there. So if you actually want to see what's coming out of your endpoints, you should use Firefox or Chrome with the JSON view extension. Because if you don't, it's just a wall of text. It's impossible to read. It's kind of a mess. And then you can also use other tools to test your endpoints, such as Postman or Insomnia. And these apps are more useful for testing things like authentication, posts, put, and delete methods, because it's a lot easier to just send and receive data from them. So the most basic WordPress endpoint is actually just slash WP-JSON. That's it. And what this does is that it returns just sort of basic information about your blog. So the name, the description, the URL, home and URL is almost always the same, what the time zone is, and the namespaces. So the namespaces are interesting because they're like what the endpoints, this is like what's installed on your site for endpoints. And it tells you right away. This is only the first part of it. If you were to actually hit JSON, you actually get a lot more. I'm a little tempted to switch over and show you live. And I'm a little afraid this is going to not work, but we're going to give it a go. So I'm just going to stop sharing for a sec and then show you that. All right, so when you hit WP-JSON, you get all the blog information. And it goes, gives you everything, gives you a lot. I'll just like let you absorb all of this. It also includes what endpoints you have. So this is my little test plugin, which I'm going to be talking about later. And right now that there's a get endpoint here and then there's another get endpoint here called cats and then there's another one called basic and then there's another one called secrets. It keeps going and this is the endpoint for posts and it just, it shows you everything. It goes so far down. You get so much information just with that one endpoint. All right, so an example, the posts endpoint. So if you go to WP-JSON slash WP, which is the namespace for WordPress itself, version two, because they're on version two of the API, slash posts. And what this does is that it just dumps all the posts available in your blog in the endpoint in a formatted thing. Again, like this little demo of code, here is only like the surface. It much like the other endpoint I just showed you, it goes on pretty far. And it also takes parameters. So again, talking about the sticky equals true, if you pass it a parameter, you can further filter the results what the API is returning to you. So then we have also, for example, the user's endpoint. The user's endpoint is a public endpoint. All users subscribed to your site, regardless of role, show up in this endpoint. It doesn't return any roles associated with the users, doesn't really return any super important information like somebody's email address, but it does return their username, which as you know, you can use to log in to a WordPress account with not just your email. And it also has the IDs. And ID number one tends to be the administrator. So you might wanna lock this endpoint down because it can be an attack vector for hackers. They find out what the username is, potentially try to figure out who's the admin, and then they'll try to brute force attack your website. So it's a good idea to turn this endpoint off. I'll talk about a little more about security later, but yeah, comes out of the box, but you should also lock it down. All right, so let's get to the meat and potatoes of this, which is building a custom endpoint. So we're gonna go step by step, super simple. So I do here have a demo plugin that you can install and pick apart the code and figure it out on your own as well. So it's just at github.com slash plank slash WCMTL dash API. I'll just leave that up on the screen for a little bit. And I believe I can put a link on the screen, so I'm gonna try that. There you go. So I believe everybody in the room can now click that and get a link to the demo plugin that I'm about to demonstrate. All right, so steps. We're gonna create a custom post type. And the reason why we're doing this is because all of the built-in post types that exist in WordPress already have their endpoints. So we don't need to create a new one if we're just using say posts, for example, or pages. Then we're gonna define the route. So we're gonna tell WordPress what we want our endpoint to actually be, the URL in which we call to get all of our JSON data. And then we're gonna call the callback function. And the callback function is basically what generates your API, the data that we're passing to the endpoint. And then we're gonna test our endpoint. And then you can build your app based on your endpoint and that app could be anything. It could be React. It could be anything you can think of, really, anything that you would use data for. All right, so next up. So the first thing we're gonna do is create the post type. And the post type is just your typical, you do it the same way that you would register a post type, register, underscore, post, underscore type. And we're gonna give it a name of, sorry, a post name. So I like to prefix my post types with something unique. So that way you don't have collisions with other things in your backend. So that we are absolutely sure that, well, my unique post type is WordCamp Montreal API underscore cap. And that's what it's called. Then we have, then you give it some labels. We don't necessarily want it to be public. So public means it's gonna have like individual pages that you can access on the front end. But we're gonna keep this one to ourselves because we want to use this custom post type specifically for our API. We do want it to show in the UI because we do want to see, we wanna be able to add cats. By the way, I'm making cats because what's the internet without cats? We don't need it to be hierarchical. It's not a page. So we don't need that. We don't need it to show and rest. So show and rest means that our new post type uses the block editor, but we don't need that. We do wanna exclude it from the search again because this is really just for our API. We want it to have the same capabilities as a post. We're gonna rewrite the slugs and then we're only saying we only really need the title, the editor and the thumbnail for our custom post type. So next is defining our route. All right, so now this is how we really make the endpoint. So the route is the endpoint or the URL that you're gonna need to get your JSON back in return. And it kinda looks like this. So it's gonna be always WP-JSON. Then it's gonna be your namespace. So you can name it whatever you want. Again, you wanna try to name it something unique so that you don't have collisions. Version one, because you gotta start somewhere. And then the endpoint, whatever you wanna name it. So in our case, because we're getting cats, it's just gonna be slash cats. Usually you wanna name it something descriptive. So as of WordPress 5.5, you need to specify the permission callback. And what this does is that it defines who has permission to access the endpoint. So if you're making a public endpoint where you don't really care who sees it or who can access it, you're just gonna return it true. In this case, it's gonna be underscore, underscore, return, underscore, true. You can also create a function here so that if you're saying like, I only want people who have the ability to upload a plugin to the site, only they can access the endpoint, you can put in a function there that either returns true or false. So if we returns true, then the information displays. If it's returned false, then WordPress will return a rest forbidden error. So next we're going to create the callback function. And the callback function is what generates the data that gets passed to your endpoint. So in my example, this is like super, super basic, but basically we have a function called getCats, which on our previous slide here, we created the callback we're saying, use the getCats function. And here we're defining that function. So in our function here, basically we wanna create an array of data. You can do this by building stuff from WP query, which is what you should be doing. Cause if you're creating a custom endpoint, then you probably aren't gonna query that endpoint, which makes the most sense. But for the sake of demonstration, all I'm showing you here is that all you need is a data array and you just need to return it in the rest ensure response function by WordPress. And then WordPress handles everything else. It'll handle the errors, it'll handle the formatting, does everything for it. That's all you really need. It's surprisingly easy. So it ensures that at the very least ensures that you get a response code and it's ideally 200. So that you get a thing. So next you would test your endpoint. And if you hit your endpoint, you should get back the array of data. So on our previous slide here, I built the array, we have Pico, Milo and Puppy. And then you have cats, like JSON array that comes back when you hit your endpoint. And that's it. And then you have your working endpoint. And then you can do whatever the heck you want with it. Make react apps, add cool animation, interactivity to your front end, do whatever you want. It's pretty cool. So here's a real world example of this in action. So this is the Carolina Performing Arts Southern Futures website. And this is their resources, the resources page. So we have a filtering system here and the list. So this one actually uses two API endpoints. And what this does, so it's resources, all the resources and then the filters, which is powered at the top here. And the result is that it's a lightning fast filtering system without needing to refresh the page. So, all right, so here's some notes about security. So for your first endpoints, create a public one. Just do a get endpoint. You don't have to worry about security as the information provided by your custom entry point should not be sensitive and it will be read only. You can create post, put and delete endpoints, but be sure to secure them. You don't want someone or an outside system accessing these endpoints and modifying your database. There is a way to lock down your endpoints so that only you can access them if you're logged in as an administrator or have specific permissions. Whatever is specified in the permissions callback, which is all the way back here, right there. Permissions callback return true. So that's public endpoint when you say return true. Back to my security slide. So you should lock it down. So if a user needs to be authenticated to interact with an endpoint, they must generate an application password and pass along the credentials. So application passwords were added in 5.6 and it allows for a way to authenticate without exposing the user's primary password. They're very much like an API key. So if you wanna test this, you can use curl in your command line where you pass the username and the password. But the password here is not the account password, it is the application password. And then you would pass it to your endpoint. So here, like your host name, which would be your domain name, WPJSON, WPV2. In this case, we're testing with the user's endpoint, context edit. So the context edit parameter here means that only people who have permission to edit will be able to access this. Yeah. So then there are two ways to authenticate natively in WordPress. You can do it with cookies or nonces and application passwords. You can use other methods like OAuth and Jacef web tokens, but you need to install plugins for those as that's not out of the box in WordPress. So I will go into more detail and show you some very scary code. Actually, it's not that scary. So I'll just take a moment to see like some of the comments here. So, yeah, what is PHP code? Well, the PHP code is WordPress is written in PHP. So you would either put this in your function.php folder but I wouldn't do that. I would create another file and initialize it in your function PHP but don't actually like put stuff in there. It's just better practice, keep your code cleaner. All right, so I'm just gonna switch screens and then I'm just gonna show you the code I need to share. So here's just the post endpoint out of the box. And I think if I pass sticky, I don't think I have any sticky point. So it's not gonna do anything. Yep, nothing, none of my posts are sticky. And I'll show you the scary user endpoint as well. So for example here, so user ID number one, well, you can probably guess that me and Christina is the admin and you should lock that down. All right, let's go check out our cats endpoint. There we go. So these are the cats that I have in the backend. And this is what it returns. I built this and it returns it. So we can go to the admin. Here we go. And right here we have cats. So this is what the, my demo plugin installs is a little cats over here. And we can add some cats and spots gonna be my own brown on this. There we go. We can even set a featured image if we want and publish it. And now when we go back to our endpoint, he should be added to the list. There he is, spot, brown shorter tabby. I will switch over and show you some code. It's not what I was intending to do but I might as well deep dive it entire screen. It wasn't letting me just share PHP Storm. So let's go the whole screen. This is not the correct project. So let's start at the beginning. So here we have register our routes. So here I'm defining my version as version one. I'm giving it the namespace of WCMTL slash V. I'm passing the version. Here I'm saying this is my namespace. My endpoint is cats. And what I intend for this endpoint to do is just give back all the cats. And so this is a get method. And we're using the callback get cats which is gonna be defined in this file over here. And the permission callback is returned true. And this means that this is a public endpoint right here. And then we have a basic and then there's the secrets thing too, which is pretty neat. So cats. So then we're gonna come and define cats over here in another file. So here what I'm doing, I'm setting up the query. I'm making it so that you can query add parameters to your endpoint by color, breed and patterns and even page number because you can do page nation as well. So we're returning 12 cats per page. We only wanna see the published cats. We're using this end point, sorry, this post type which is underscore cat with my slug, if you will, my unique slug. And then we're building the query. So this is kind of scary. I didn't really wanna get into the query stuff but basically you can build your query. And so here I'm saying if these parameters are stated you can then filter by color, breed and so on and so forth. And then down here I'm building the array. I'm building that array that I showed you earlier as a simple thing. That is gonna be returned. So then here it is, it's gonna be, this is what I want to return in my API endpoint. Just building the array. Here I'm returning a custom error. If say you wanna return a custom error, you can do that. There's a new return, new error. You give it the status. We usually say 200 even if it's an error because we want it to say no cats found and that is a valid response. And then here we just return it all with rest ensure response. I know this looks very scary but it's a lot simpler. So this is the basic version. So if we did slash I made another endpoint called slash basic and slash basic just literally returns a predefined array using the rest assure response and that's it. And then I also have a secret one that's not it secrets. So this is the secret endpoint that I also built. I'm gonna show you how to demonstrate how you could use insomnia. I prefer insomnia to postman to use the application key. Sorry, the application password. So the application password is here. So if you wanna create an application password for a user, you just, you can select the user and then you come here and you literally create a new application password. And here is my API key and then you can also revoke it. So if you ever have a security breach or something, you can get rid of it. So I will show you in insomnia quickly when... So here I'm passing my username. I'm passing the key that WordPress generated for me. It only shows you once. So you gotta copy it down somewhere safe. And if I don't pass my password and I hit my secrets endpoint, I get that rest forbidden because I've said that unless you're logged in and unless you have permission to upload plugins, you cannot see this endpoint. So if I do log myself in and pass my username and my API key, I will get back all the secrets. And that's how you lock it down. So there we go. So that's basically it. So step one, register your post type. Step two, register your route. Step three, create the meat and potatoes of your API endpoint and then you test your endpoint and then you can create, build an app is really cool. So now we're onto the Q and A. So there we go. So I'm looking on the sessions tab for questions. So from Paulo we have, is there any or will there be native support for GraphQL? I know there's a plugin to enable this. There is no native GraphQL as far as I know right now. I don't think it's on the timeline. I'll be honest. So I don't really know. But I've used the GraphQL plugin before. It's a pretty good plugin. So until they have talks about putting this in natively which I'll be honest. I don't feel like it's on the roadmap. I would use the GraphQL plugin. It's very, very good. And let's see. And George asks, are there any tutorials slash resources that you recommend for beginning learning how to use the REST API? Yeah, actually honestly, the WordPress documentation is fantastic. It's really good. It's really detailed. Off the top of my head, I can't really think of any other resources in that right now. Because I'm a very hands-on learner, I just muck around and try things until they break. If you haven't downloaded the demo plugin, I suggest that you download my demo plugin and then you can pick apart all my code and you can try to like rebuild it yourself. It's a good place to start. So let's see. Any other questions? Well, Jerome says, very impressive and inspired me. Thank you, not a question. That's okay. Yeah, actually, you know what? I'm gonna just take this moment to show you the endpoint in action because it's honestly really cool. So now that's the login. I wanna go to the login. I wanna go to the resources. Ta-da. Oh, nope. There we go. So this is my demo of it. It's not a demo. This is a live site. This is a real site that's using us right now. So right now they only have seven entries, but this library will grow. So you can filter and see how fast that was. Like that was like crazy fast. You know, you want it. And the page doesn't refresh. You can combine filters as well. So this is like a real world example. Of the API endpoint in action. Oh, I could also show you, I forgot, but I actually did have parameters here. So if I wanted to specify color as a parameter, I'm gonna say color brown. It should only return. Okay, so there we go. Oh, that didn't really work. Oh. Well, that's embarrassing. My endpoint isn't working. Yeah, these things happen. Tabby, oh, that's a tad awkward. But it does work. That's what I had built in this big scary thing over here. Show the code calling this, calling the other page. Do you mean routes? So my little test API here has three end points. It has cats. It has basic and it has the secrets one, which you need a password to get. Carolina, oh, okay. Yeah, sure. That's over here. Okay, so the thing, the connecting point here is that this is being generated by React. And React is hitting the end points to generate this front-end code. I'm not talking about React as one I'm actually just learning React to be quite frankly, honest. So the React, I can't unfortunately show you the code for this, but it's two end points here. That's, so this is one endpoint and then the actual results are the other endpoint. That still helps. Okay, that's good. So what I mean React, I mean it's like you do things like AJAX calls, right? You do an AJAX call to your endpoint and then that gives you the data that you then run through your React app and then you can do whatever you want with it. So here, this one, the resources endpoint here is just returning all of the resources and then there's another endpoint here that's returning all of the filters and then we do some React magic on the front-end that does the filtering, but it's insanely fast. Like I'm not even refreshing the page here. It's like really cool. Nope, no audio, interesting. There we go. Thanks, Megan. So Megan says that you can use axios to hit the endpoint to get the results from the back-end. That's exactly it. Okay, and talk about securing strategy not like giving access to specific routes. Okay, so I'll go back to the security part. So the security here. So here's the permission callback. So when you're defining your route, you can create a function here that says that returns either true or false. It says, who can access this point? So in the sense of like what you couldn't do for like in the sense of locking down the user's endpoint, you can basically un-set it. So there's a filter in WordPress that gets you, you can get like the endpoints and then you can just like un-set that from the array. And then when you try to visit it, you won't be able to get to it. So an example of this is that was it. Users, you're not currently logged in. So like we locked down this endpoint, you can no longer see it. Under normal circumstances out of the box WordPress, you would be able to access this, but we've locked it down. Is there a way to connect to WP websites through SSO through OAuth? Maybe, I'll be honest, I don't really know. OAuth is not native to WordPress. So if you wanna use OAuth, you're gonna have to download a plugin that does that. But you could connect to WordPress sites together with something in the middle. I don't see why not. The OAuth part though is not native to WordPress. So sorry, I can't answer their questions. Another thing you can do with it is you can also ingest another API and then put it through your own API endpoint. So you can do stuff like pull in data from another API. You can save it to a local JSON file that say like refreshes every 24 hours. And then your own endpoint can access the JSON file that's saved. And then this way you can create a buffer. It's also how you can stop hitting your... Cause like some APIs have rate limits, right? So if you're only hitting your own file, you're not hitting the endpoint as often. Got another five minutes for questions and I can just keep... How would you prevent slash users to return any data after enabling REST like specifically this existing route? Okay, I'll see if I can dip up a piece of code that does this, cause off the top of my head I don't really remember, but you basically like unset it from the array. I'll see if I can find it for you. Aha, okay, here we go. Restrict user endpoints. So this is what you do. So you can like come, there is a filter here. So there is an action. So you add the filter REST endpoints and you pass it a function and the function is this. So what this does is like, if the user is not logged in, you unset the endpoint. And then if they are logged in, well then you let them see the endpoints. It's just that simple. Jerome, I would suggest you grab a screenshot if you want to use the snippet. I just used remove action. Yeah, see this approach, when you try to use that filter, it will lock everything down, which is not necessarily what you want. You're gonna want it to let some things through. What is the filter again? Oh yes, sorry, that's at the top. That's up here. So it's REST underscore endpoints is the filter. And then you just pass it your callback function over there and it's all the way down here, which is this guy right here. So that's how you would like lock down an endpoint, for example. For those who are not super code savvy, there is a plugin that will let you just turn off user endpoints. It's a very easy solution if you don't want to muck about in this. I don't know the name of the plugin off the top of my head, but it's got a very boring name, something like lockdown user endpoints. And you can just install it and it basically does this for you. There you go. So that is my talk. I've got two more minutes for questions. But here are my socials, at least related to WordPress. So I do write blog posts. I do plan on writing a blog post about the talk that I gave today. It's gonna be at dev.to slash cero fellow. I have my WordPress profile, if you feel like spying on me. And I also have my LinkedIn there as well. Well, I'm glad that my talk helped someone today. So that makes me feel great. Thanks, Jerome. Yes, please do. Please break stuff. It's the best way to learn. Although I apparently already broke my plugin myself, so I'm gonna have to fix it before you can break it some more. So I think that's more or less time for me. Oh, I'm glad you talked so, thank you so much. So that's my time. Thank you for having me. This was great. I hope you learned something and feel free to ask me questions and download the plugin and break it. Do it, break it. It's fun.