<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Woolf</title>
    <description>The latest articles on DEV Community by David Woolf (@david_woolf).</description>
    <link>https://dev.to/david_woolf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628430%2Fd32f9df5-f9df-49f3-b543-580283e42caa.jpeg</url>
      <title>DEV Community: David Woolf</title>
      <link>https://dev.to/david_woolf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/david_woolf"/>
    <language>en</language>
    <item>
      <title>Modify WordPress REST routes with register rest field</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Tue, 28 Sep 2021 20:26:42 +0000</pubDate>
      <link>https://dev.to/david_woolf/modify-wordpress-rest-routes-with-register-rest-field-2nk</link>
      <guid>https://dev.to/david_woolf/modify-wordpress-rest-routes-with-register-rest-field-2nk</guid>
      <description>&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;register_rest_field&lt;/code&gt; function is a PHP function that allows you to add extra fields to any registered endpoint (posts, pages, custom post types, terms, users, etc). The function takes three parameters:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;register_rest_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$object_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$args&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;$object_type&lt;/code&gt; parameter is any data type in WordPress, and can be an array of multiple types, or a string for a single type. Next, the &lt;code&gt;$attribute&lt;/code&gt; parameter is the name of the field you want to register and will show up in the rest response as the key name.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;$args&lt;/code&gt; parameter is an array with a getter, setter, and schema definition. All three arguments are optional, so you have a lot of flexibility in how you control your field.&lt;/p&gt;
&lt;h2&gt;
  
  
  Registering a field
&lt;/h2&gt;

&lt;p&gt;Let’s build a real example. In this case we’re going to register a field for posts that shows how many “slaps” the post has, along with a setter to add slaps whenever the user clicks a “slap this post” button.&lt;/p&gt;

&lt;p&gt;First we want to target posts and name our attribute:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// ... getters and settings&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Note: wrap your &lt;code&gt;register_rest_field&lt;/code&gt; calls in the &lt;code&gt;rest_api_init&lt;/code&gt; action to ensures the rest api is loaded&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting the value
&lt;/h3&gt;

&lt;p&gt;While the above is the only required code to use the &lt;code&gt;register_rest_field&lt;/code&gt; function, the field won’t show up in your REST endpoint without at least a get value. Let’s take care of that now:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// NEW CODE&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'get_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_post_meta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;get_callback&lt;/code&gt; argument accepts an &lt;code&gt;$object&lt;/code&gt; parameter, which in this case is an individual post (passed as an array). Inside of the callback we can use standard WordPress functions like &lt;code&gt;get_post_meta&lt;/code&gt;. In this case, we are grabbing the slap_count meta field and returning either the value or 0.&lt;/p&gt;

&lt;p&gt;If you query an single post using the &lt;code&gt;/wp-json/wp/v2/posts/&amp;lt;id&amp;gt;&lt;/code&gt; endpoint, you should see this line in the response:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"slap_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;whatever&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For our example, the field so far is pretty useless but if you just wanted to output a value directly then the above is all you need.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting the value
&lt;/h3&gt;

&lt;p&gt;To allow updates to the value, add a &lt;code&gt;update_callback&lt;/code&gt; argument to the &lt;code&gt;$args&lt;/code&gt; array:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'get_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_post_meta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="c1"&gt;// NEW CODE&lt;/span&gt;
            &lt;span class="s1"&gt;'update_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_post_meta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="nf"&gt;update_post_meta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$slap_count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;update_callback&lt;/code&gt; function takes two parameters: &lt;code&gt;$value&lt;/code&gt; and &lt;code&gt;$object&lt;/code&gt;. In our case we aren’t using the value variable, but instead just adding 1 to the value whenever the callback is fired.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: in this function &lt;code&gt;$object&lt;/code&gt; is passed as an object type instead of an array like &lt;code&gt;get_callback&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Triggering an update
&lt;/h3&gt;

&lt;p&gt;To actually fire the &lt;code&gt;update_callback&lt;/code&gt; function, simply call the &lt;code&gt;/wp-json/wp/v2/posts/&amp;lt;id&amp;gt;&lt;/code&gt; endpoint with the POST method, and pass the field name through the body as JSON:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Javascript example&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/wp-json/wp/v2/posts/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// make sure to authenticate or pass the X-WP-Nonce value as a header&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slap_count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;// reminder that the value doesn't matter for our example as we just increment the count by one&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... the updated post object is returned here&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Securing your field
&lt;/h2&gt;

&lt;p&gt;As always, a little security goes a long way. The third parameter in the &lt;code&gt;register_rest_field&lt;/code&gt; $args array is a schema array with sanitization and validation options:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'slap_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="c1"&gt;// ...get_callback&lt;/span&gt;
            &lt;span class="c1"&gt;// ...update_callback&lt;/span&gt;

            &lt;span class="c1"&gt;// NEW CODE&lt;/span&gt;
            &lt;span class="s1"&gt;'schema'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt; &lt;span class="c1"&gt;// the type of value we expect to be passed back&lt;/span&gt;
                &lt;span class="s1"&gt;'sanitize_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// run sanitization here&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s1"&gt;'validate_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="c1"&gt;// run sanitization here&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;schema&lt;/code&gt; parameter takes three arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the type of the value (int, string, boolean, etc)&lt;/li&gt;
&lt;li&gt;A sanitization callback to sanitize the input&lt;/li&gt;
&lt;li&gt;A validate callback to make sure it conforms to some set of rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven’t already, read more on sanitizing and validating values accepted into your rest routes &lt;a href="https://indexforwp.com/how-to-secure-your-own-rest-api-routes-in-wordpress/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The same options can be used in the schema callback functions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;In just a few lines of code, you can completely customize WordPress’ built-in REST routes with your own data. Or combine and extend existing values to avoid unnecessary work in Javascript and prevent multiple REST calls to grab necessary data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628430%2Fd32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>javascript</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Generating WordPress Application Passwords for your third party apps</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Wed, 08 Sep 2021 10:00:00 +0000</pubDate>
      <link>https://dev.to/david_woolf/generating-wordpress-application-passwords-for-your-third-party-apps-571a</link>
      <guid>https://dev.to/david_woolf/generating-wordpress-application-passwords-for-your-third-party-apps-571a</guid>
      <description>&lt;p&gt;In our Postman walkthrough, we went over how to generate application passwords for a single user and pass it with each REST request to handle authentication. For real world use, asking users to go login to their account, generate a password, and copy it back into another app is a lot of friction. Luckily we can create a workflow to make this easier.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: we’ll be using Javascript and PHP for all examples in this article&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;First, we need to verify the specific WordPress installation supports application passwords and if so, what the authorization url is (we’ll use this later to automate some of the steps to create a password). Assuming we know the website URL, we just need to do a GET request to the website’s main REST endpoint (wp-json):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://theory.local/wp-json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// check the authentication value here&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note: For these examples, I am using the Local app with SSL enabled. You must have an SSL connection to handle application password requests&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inside of our fetch statement, we’re requesting the &lt;code&gt;wp-json&lt;/code&gt; endpoint which will return the overall API structure of the site as a JSON object. Inside this object, we’re looking for the &lt;code&gt;authentication&lt;/code&gt; property. If it’s missing or empty, then we can’t do authentication on the site. If authentication is enabled, it will return an object that contains the authorization endpoint:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"application-passwords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"endpoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;https://theory.local/wp-admin/authorize-application.php&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you go to that url and login, you’ll see something like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NF8cgev8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/indexforwp.com/wp-content/uploads/2021/09/1.png%3Fresize%3D1024%252C514%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NF8cgev8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i1.wp.com/indexforwp.com/wp-content/uploads/2021/09/1.png%3Fresize%3D1024%252C514%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without passing in some parameters, it functions just like the application password section when editing a user in the dashboard. Here are the parameters we can pass:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;app_name (required): human readable name (you app name, etc)
app_id (optional, but recommended): UUID string
success_url (optional, but recommended): the url to send the user to if they approve the connection. Supports multiple protocols, EXCEPT for the non-secure http://
reject_url (optional): the url to send the user to if they reject the application. Supports multiple protocols, EXCEPT for the non-secure http://
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The success URL will be appended with three parameters: &lt;code&gt;site_url&lt;/code&gt;, &lt;code&gt;user_login&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt;. Also, if you don’t pass a &lt;code&gt;reject_url&lt;/code&gt; value, it will go to the &lt;code&gt;success_url&lt;/code&gt; value and add &lt;code&gt;?success=false&lt;/code&gt; (this might be preferred if you want to manage everything from one page).&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating your own app authentication
&lt;/h2&gt;

&lt;p&gt;To provide an example of creating an application password for your app to connect to WordPress, we’re going to create a simple, local HTML/PHP form that takes the user to another local WordPress instance, generates the password and passes it back.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up our form
&lt;/h3&gt;

&lt;p&gt;Our form will be pretty basic, just an input to enter the website URL and a submit button (I’ve omitted styling code to make this more concise):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; 
&lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"create-authentication-password"&lt;/span&gt;
&lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;
&lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;
        Connect your site
    &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; 
    &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;
            Your Website URL
        &lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
        &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt;
        &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt; 
    &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt; 
    &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"https://"&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;
    &lt;span class="na"&gt;pattern=&lt;/span&gt;&lt;span class="s"&gt;"https://.*"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; 
    &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We’re using some newer technologies to quickly validate that the input is filled out and is a valid https url. Then we just have a standard submit button. Our form action is &lt;code&gt;/&lt;/code&gt; because that’s the page URL I have it on, and we’ll be using Javascript to send the form. Here is how the form looks (again, I have CSS classes added):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ODlJefYa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/indexforwp.com/wp-content/uploads/2021/09/2.png%3Fresize%3D1024%252C530%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ODlJefYa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i0.wp.com/indexforwp.com/wp-content/uploads/2021/09/2.png%3Fresize%3D1024%252C530%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Using Javascript to submit the form
&lt;/h3&gt;

&lt;p&gt;We’re going to use ES6 syntax, and to get started we want to listen for the form submission:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;create-authentication-password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="c1"&gt;// take action here...&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we want to grab our input value. We can create a new &lt;code&gt;FormData&lt;/code&gt; class, pass in our form and grab our input named &lt;code&gt;website&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;create-authentication-password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="c1"&gt;// NEW CODE&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we want to do our GET request on &lt;code&gt;wp-json&lt;/code&gt; like we discussed initially:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;create-authentication-password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// NEW CODE&lt;/span&gt;
            &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/wp-json`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="c1"&gt;// do an action here&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, we’ll verify application support is available, grab the url to generate a new password, and pass in some parameters to redirect the user back:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;document&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;create-authentication-password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/wp-json`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="c1"&gt;// NEW CODE&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authentication&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authentication&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authentication&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application-passwords&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt;
                        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;?app_name=Sandbox Website&amp;amp;success_url=https://sandbox.local/success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let’s go over the new code line by line. First, we check for support with Javascript’s &lt;code&gt;key in object&lt;/code&gt; code and ensure it’s not false:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authentication&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authentication&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since the condition code will only fire if there is application password support, the rest of the code can setup the final url to go to:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authentication&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application-passwords&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;?app_name=Sandbox Website&amp;amp;success_url=https://sandbox.local/success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our root URL is the provided application password authorization URL from our fetch request. The params are a simply URL parameters string with our app name and success url (in production code, make sure to pass in an app_id).&lt;/p&gt;

&lt;p&gt;Finally, we do a simple &lt;code&gt;window.location&lt;/code&gt; page send with our root and body:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This code will take the user to the inputted website and, if they click “Yes, I approve of this connection”, the site url, username, and application password will be sent back as URL parameters (this is why using https:// is important to prevent someone capturing these values). On my success page, I output these values as an example, and here’s what they look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OhSKrgeT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/indexforwp.com/wp-content/uploads/2021/09/3.png%3Fresize%3D1024%252C491%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OhSKrgeT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i2.wp.com/indexforwp.com/wp-content/uploads/2021/09/3.png%3Fresize%3D1024%252C491%26ssl%3D1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;That’s all you need to create a simplified application password flow for your users! This is a basic authentication system where you pass back the username and password using base64 encryption. You should also make sure you encrypt the values when storing them to prevent security issues. Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
  
    .ltag__user__id__628430 .follow-action-button {
      background-color: #000000 !important;
      color: #ffffff !important;
      border-color: #000000 !important;
    }
  
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5srIcvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--zYYDI4-z--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/628430/d32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>javascript</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Handling Permissions in your WordPress REST routes</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Mon, 06 Sep 2021 09:00:00 +0000</pubDate>
      <link>https://dev.to/david_woolf/handling-permissions-in-your-wordpress-rest-routes-c6j</link>
      <guid>https://dev.to/david_woolf/handling-permissions-in-your-wordpress-rest-routes-c6j</guid>
      <description>&lt;p&gt;In our previous walkthroughs on &lt;code&gt;register_rest_route&lt;/code&gt; we added this line of code to our registration function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This was to prevent permissions issues for our sandbox code, but in a production environment you would only use this for fully public API endpoints, and never for endpoints related to a user.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: if you are building a public API then the above is what you should use.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Handling permissions in your routes
&lt;/h2&gt;

&lt;p&gt;Just like validating user input for your route, the permissions callback is a function where you return either true, false, or a WP_Error instance:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;[a-zA-Z0-9_-]+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="c1"&gt;// ... other arguments stripped for readability&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// ... permissions check goes here&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The permissions callback is run after the current user is set, which would be either the matching user in the dashboard or an authenticated user you passed in your request. As this is WordPress, our permissions checks will use functions provided by WordPress, mainly &lt;code&gt;current_user_can&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The callback also receives the entire request so you can perform conditional logic depending on the data passed in.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to check user capabilities in WordPress
&lt;/h2&gt;

&lt;p&gt;WordPress uses a roles and capabilities system to handle what a user is allowed to do. A role is basically a set of capabilities that you can quickly assign to users. Examples of built-in roles are administrator, author, editor, and subscriber.&lt;/p&gt;

&lt;p&gt;A capability is a singular action a user is either allowed or not allowed to do. The system is additive, so if the user has the capability it means they can do the specified action (ie: don’t create capabilities like &lt;code&gt;cannot_do_action&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The quickest way to verify a user can do something is by using the &lt;code&gt;current_user_can&lt;/code&gt; function. This function takes a string that matches a capability and returns true or false:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;current_user_can&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'edit_posts'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true or false&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;There are a lot of different capabilities built-in to WordPress, and you can add custom ones as well. We won’t go through the list, but you can view the list here &lt;a href="https://wordpress.org/support/article/roles-and-capabilities/#capabilities" rel="noopener noreferrer"&gt;https://wordpress.org/support/article/roles-and-capabilities/#capabilities&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Performing a permissions check
&lt;/h2&gt;

&lt;p&gt;Let’s go back to our rest route and add a permissions check. Let’s say theoretically that our route was to update global settings for the WordPress installation. We’ll use the built-in &lt;code&gt;manage_options&lt;/code&gt; capability, which allows users to access and update all of the settings in the dashboard:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;[a-zA-Z0-9_-]+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;current_user_can&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'manage_options'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;This was a short walkthrough, but that’s because creating permissions is pretty simple! It really just depends on how you design your user system and security levels (fortunately WordPress provides a lot of this up front for whats included out of the box). I would recommend looking closely at the capabilities provided. We’ll also go through creating capabilities and recommended plugins for more advanced patters like policies in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628430%2Fd32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>javascript</category>
      <category>php</category>
    </item>
    <item>
      <title>How to secure your REST API routes in WordPress</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Wed, 01 Sep 2021 10:00:00 +0000</pubDate>
      <link>https://dev.to/david_woolf/how-to-secure-your-rest-api-routes-in-wordpress-3de5</link>
      <guid>https://dev.to/david_woolf/how-to-secure-your-rest-api-routes-in-wordpress-3de5</guid>
      <description>&lt;p&gt;In our last &lt;a href="https://indexforwp.com/how-to-create-your-own-rest-routes-in-wordpress" rel="noopener noreferrer"&gt;article&lt;/a&gt; we looked at creating your own routes in the WordPress REST API using &lt;code&gt;register_rest_route&lt;/code&gt;, along with some basic examples of requiring and checking for parameters. Today, we’ll go over a better way to handle validation and sanitization for data passed to your routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where we left off before
&lt;/h2&gt;

&lt;p&gt;Here is the final code we ended up with in our last session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EDITABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'another_callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// our new route&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;\d+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function_with_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We created a route called &lt;code&gt;my-endpoint&lt;/code&gt; with GET and POST methods that do not require a parameter passed in, along with a similarly named route that requires an integer at the end (for example: &lt;code&gt;my-endpoint/10&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;
  
  
  Defining arguments
&lt;/h2&gt;

&lt;p&gt;In our previous &lt;a href="https://dev.to/how-to-create-your-own-rest-routes-in-wordpress"&gt;article&lt;/a&gt;, we created a new route that required an integer at the end:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// requires an id parameter, which must be a number&lt;/span&gt;
&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;\d+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function_with_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once again, here is how the regular expression defining the  works:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;'(?P&lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;d+)' // the full argument (parathenses are to group it)
'?P' // denotes that this is a parameter
'&lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;' // the name of the parameter
'&lt;span class="se"&gt;\\&lt;/span&gt;d+' // indicates the paramter should be an integer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While regular expression are hard to read, this one takes care of a couple things we’ll cover in this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The route will not run if the id is missing (in our case, the original rest route will run, which can be intentional)&lt;/li&gt;
&lt;li&gt;An error will be sent back if the id is not an integer (although it will just say the route doesn’t exist)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also a few of things this style won’t do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The route won’t send a proper error back if the type is wrong (what if we want to let the user know they need to send an integer versus an ambiguous error about the route not existing)&lt;/li&gt;
&lt;li&gt;The data won’t be sanitized in any custom way (for example: the ID needs to be less than 10)&lt;/li&gt;
&lt;li&gt;We can’t pass in a default value&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Adding additional checks for the argument:
&lt;/h3&gt;

&lt;p&gt;To add the features described above, all we need to do is add an argument called args to our method:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;\\d+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function_with_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'args'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="c1"&gt;// parameters go here&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The args argument is a keyed array, with each key corresponding to the parameter. The key values are also an array with 4 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;default: default value if the parameter is missing&lt;/li&gt;
&lt;li&gt;required: set the parameter to be required or not&lt;/li&gt;
&lt;li&gt;validate_callback: a function to validate something about the parameter. Returns true or false, and will send a formatted error back if false.&lt;/li&gt;
&lt;li&gt;sanitize_callback: a function to sanitize the data before sending it to the callback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s interesting about these options is that, because of how we defined our parameter in our route name, we already have done most of this work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the parameter is required&lt;/li&gt;
&lt;li&gt;the parameter must be an integer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For testing, let’s change our route to pass in as many data types as possible:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;[a-zA-Z0-9_-]+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function_with_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'args'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We now have a new regex expression &lt;code&gt;(?P&amp;lt;id&amp;gt;[a-zA-Z0-9_-]+)&lt;/code&gt; which lets us pass in strings or numbers. Next, let’s add all of our available arguments into the args array:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;[a-zA-Z0-9_-]+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function_with_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'args'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="c1"&gt;// NEW CODE HERE&lt;/span&gt;
                    &lt;span class="s1"&gt;'default'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'required'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s1"&gt;'validate_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s1"&gt;'sanitize_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The sample above has been coded to basically be useless. Validation always returns true and sanitization just returns the value untouched. Let’s break down each argument:&lt;/p&gt;
&lt;h3&gt;
  
  
  Default value
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;default&lt;/code&gt; argument provides a default value if none is passed. Because we are encoding the parameter as part of the route name, this code will never be called. Not providing a value in the URL will either return an error that the route does not exist, or call another endpoint with the same name that does not have a parameter attached to the end (in our example, we have &lt;code&gt;my-endpoint&lt;/code&gt; and &lt;code&gt;my-endpoing/&amp;lt;id&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Requiring a value
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;required&lt;/code&gt; argument lets you defined an argument as required or not. Again, because we are encoding the parameter as part of the route name, this code will never be called.&lt;/p&gt;
&lt;h3&gt;
  
  
  Validation
&lt;/h3&gt;

&lt;p&gt;Validating parameters is a great way to quickly check a parameter and say that it is either valid (true) or not valid (false). You only return true or false in &lt;code&gt;validate_callback&lt;/code&gt;. Here is an example where an id greater than 10 will be considered invalid:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'validate_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Sanitization
&lt;/h3&gt;

&lt;p&gt;Sanitization of parameters is different from validation because we return the value back in some form. Note that &lt;code&gt;sanitize_callback&lt;/code&gt; and &lt;code&gt;validate_callback&lt;/code&gt; do not get called in any specific order, and are simply additional filters to ensure whatever data passed in fits the logic of the original callback function. In our example, let’s remove negative numbers:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'sanitize_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$integer_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$integer_value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$integer_value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, with our &lt;code&gt;validate_callback&lt;/code&gt; and &lt;code&gt;sanitize_callback&lt;/code&gt; functions we have ensured only numbers 0-10 are allowed to be passed through.&lt;/p&gt;
&lt;h2&gt;
  
  
  Additional arguments for quick validation and sanitization
&lt;/h2&gt;

&lt;p&gt;There are a many more args for quickly validating a parameter without using function callbacks:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// array | object | integer | number | string | boolean | null&lt;/span&gt;
    &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// a description used in the API schema&lt;/span&gt;
    &lt;span class="s1"&gt;'format'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// hex-color | email | date-time | ip | uuid&lt;/span&gt;
    &lt;span class="s1"&gt;'enum'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// array of allowed values&lt;/span&gt;
    &lt;span class="s1"&gt;'minimum'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// minimum integer value (inclusive)&lt;/span&gt;
    &lt;span class="s1"&gt;'maximum'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// maximum integer value (inclusive)&lt;/span&gt;
    &lt;span class="s1"&gt;'exclusiveMinimum'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// minimum integer value (exclusive)&lt;/span&gt;
    &lt;span class="s1"&gt;'exclusiveMaximum'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// maximum integer value (exclusive)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note: the format option requires the type to be defined as a string&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Ensuring user input to any function, method or API should always be verified before taking action. While you can do all of the above in the full callback function for your route, it’s preferred to separate this out and prevent the callback from ever being fired if something is wrong.&lt;/p&gt;

&lt;p&gt;I also want to make sure it’s stressed that you can (and should) create as many rules for any parameters used in your callback, not just the ones that might be defined as part of your endpoint name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628430%2Fd32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>php</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to create your own REST routes in WordPress</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Mon, 30 Aug 2021 10:00:00 +0000</pubDate>
      <link>https://dev.to/david_woolf/how-to-create-your-own-rest-routes-in-wordpress-32og</link>
      <guid>https://dev.to/david_woolf/how-to-create-your-own-rest-routes-in-wordpress-32og</guid>
      <description>&lt;p&gt;WordPress makes registering custom rest routes really easy with a function called &lt;code&gt;register_rest_route&lt;/code&gt;. This function provides options to create a namespace (which you can also use to version your APIs), all of your route names, an args array to create CRUD operations and check security, and even set your route to override or merge with existing routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function definition
&lt;/h2&gt;

&lt;p&gt;Let’s review the function parameters and see what we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nv"&gt;$route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nv"&gt;$override&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;namespace&lt;/strong&gt; : a required string which should be the same for all of your routes in the api you are creating&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;route:&lt;/strong&gt;  the required string for the singular API endpoint, which would include some of the following methods: GET, POST, PUT, DELETE&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;args:&lt;/strong&gt;  optional array of options or array of array of options (we’ll go over this in detail)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;override&lt;/strong&gt; : optional true or false. True will replace an existing route while false will merge it and override any duplicate methods (defaults to false, so you can normally omit it)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Registering a route
&lt;/h2&gt;

&lt;p&gt;To register a route, we need to call it inside of the &lt;code&gt;rest_api_init&lt;/code&gt; hook:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c1"&gt;//...we'll work in here&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The first argument is the namespace. It’s important to note that your namespace should not include a beginning or trailing slash, and should be composed of your namespace and version number (for example, WordPress’s built-in routes use &lt;code&gt;wp/v2&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// we'll omit the action hook line from the rest of the examples:&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// route name&lt;/span&gt;
        &lt;span class="c1"&gt;// args&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we will create our route name. This will be the last part of the URL we call to access this route. Because this is a URL, you should name it the way you would see a URL (dashes instead of underscores, etc) and avoid characters like &lt;code&gt;, % [] { } # ( ) * &amp;amp;&lt;/code&gt; and spaces:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// args&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, we add our args. Because of the scope of the args parameter, we’ll be going over the basic pieces in the next section&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding methods, permissions, and a callback function
&lt;/h2&gt;

&lt;p&gt;The most basic use of the args parameter is this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt; &lt;span class="c1"&gt;// this can any function name,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This small amount of code will create a new route with a GET method that calls the &lt;code&gt;callback_function&lt;/code&gt; function. However, there are a couple of recommendations to make this better:&lt;/p&gt;
&lt;h3&gt;
  
  
  Permissions
&lt;/h3&gt;

&lt;p&gt;With newer versions of WordPress, you are asked to set the permissions for your routes. It’s not required but you will get a warning message. To create a public route, just add this line to your args array:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt; &lt;span class="c1"&gt;// new permissions line&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Another way to set methods
&lt;/h3&gt;

&lt;p&gt;Because there are multiple methods that seem very similar (POST vs PUT etc), WordPress provides some constants as part of the &lt;code&gt;WP_REST_Server&lt;/code&gt; class to make your method names more clear:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;WP_REST_Server::READABLE // methods: GET
WP_REST_Server::EDITABLE // methods: POST, PUT, PATCH
WP_REST_Server::DELETABLE // methods: DELETE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You don’t need to instantiate the class so to use these just update the first line of your args statement:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt; &lt;span class="c1"&gt;// was previously 'GET'&lt;/span&gt;
    &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That’s all you need to declare a basic route (minus the callback function of course). Let’s see the code all together:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Creating your callback function
&lt;/h2&gt;

&lt;p&gt;The callback function for your route is a normal PHP function, but it receives a full &lt;code&gt;$request&lt;/code&gt; object as it’s parameter:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;callback_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do stuff here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;$request&lt;/code&gt; parameter is a &lt;code&gt;WP_Rest_Request&lt;/code&gt; instance and can contain body data, url parameters, and more. Now, let’s look at how we can return some data.&lt;/p&gt;
&lt;h3&gt;
  
  
  Returning data correctly
&lt;/h3&gt;

&lt;p&gt;If you haven’t looked at our post on using &lt;code&gt;rest_ensure_response&lt;/code&gt; I would give it a glance &lt;a href="https://indexforwp.com/function-breakdown-rest_ensure_response/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. You can skip to the end to see an example. The function returns your data with a 200 OK response header and any type of data you pass back (strings, arrays, etc). Here is a useless return value for our new route:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;callback_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hello world!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you are working along with this article, you can test this yourself by adding the following to your base URL: &lt;code&gt;/wp-json/ndx/v1/my-endpoint&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: if you get a 404, it may be your permalinks. Go to Settings &amp;gt; Permalinks in the dashboard and turn on Pretty Permalinks. The specific style doesn’t matter, any of them will ensure /wp-json works correctly&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your route is setup correctly, you should see &lt;code&gt;hello world!&lt;/code&gt; in the browser.&lt;/p&gt;
&lt;h3&gt;
  
  
  Testing URL parameters
&lt;/h3&gt;

&lt;p&gt;Now that we can return data, it would be nice to read data sent along with the API. If you’ve ever used URL parameters before, this should be straightforward. Change your callback function to this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;callback_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hello &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The&lt;code&gt;get_param&lt;/code&gt; method is available from our &lt;code&gt;WP_Rest_Response&lt;/code&gt; instance, and can be used to read any URL parameters passed with the route. To test this, add the following to your base URL:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/wp-json/ndx/v1/my-endpoint?name=YOUR NAME&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should see “hello YOUR NAME!”&lt;/p&gt;
&lt;h3&gt;
  
  
  Basic error handling
&lt;/h3&gt;

&lt;p&gt;If you remove the name parameter from the URL the result looks malformed. We can handle this by checking for the name param in our callback function and returning an error if it’s missing:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;callback_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hello &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WP_Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'missing_fields'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'please include name as a parameter'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note that there is a better way to handle required input, which we’ll cover in our next article about data sanitization, but this is a completely valid way to check for a value. Also, do not try to use &lt;code&gt;isset&lt;/code&gt; with the &lt;code&gt;get_param&lt;/code&gt; method, as it already checks for this and returns null if it can’t find the parameter.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding additional methods to your route
&lt;/h2&gt;

&lt;p&gt;Let’s go back to our route registration code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you wanted to add a POST method for your route, you might think of adding another &lt;code&gt;register_rest_route&lt;/code&gt; function declaration. That would required duplicating a lot of code with the same values. Instead, let’s change our args array to be an &lt;em&gt;array of arrays:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EDITABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'another_callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notice how we now have two arrays that are very similar, but the second one’s method is EDITABLE and the callback function is different. This means you’ll need to create another function to handle this endpoint:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;another_callback_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'I show up when you call `my-endpoint` with the POST, PUT, or PATCH method'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you add this code and refresh your browser you’ll notice you don’t see this message. That’s because accessing a WordPress API endpoint in the browser is always a GET request. To test other types of requests, you’ll need to use a library or something like Postman. We just posted a thorough tutorial on how to use Postman &lt;a href="https://dev.to/using-postman-with-the-wordpress-rest-api"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: generally non-GET requests require authentication, but we are passing in our public permission callback, so you can skip that section of the Postman article and just get set up to play around with it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you get set up in Postman, just make sure you change the method to POST, click the “Send” button and you should see this at the bottom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Findexforwp.com%2Fwp-content%2Fuploads%2F2021%2F08%2Fpostman.png%3Fresize%3D1024%252C402%26ssl%3D1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Findexforwp.com%2Fwp-content%2Fuploads%2F2021%2F08%2Fpostman.png%3Fresize%3D1024%252C402%26ssl%3D1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Requiring values as part of the route
&lt;/h2&gt;

&lt;p&gt;While URL parameters are a nice and flexible feature to send data to your route, you can also add data as part of the endpoint itself. For example, WordPress lets you access posts by going to &lt;code&gt;wp-jons/wp/v2/posts&lt;/code&gt; but it also lets you look at a single post by going to &lt;code&gt;/wp-json/wp/v2/posts/&amp;lt;id&amp;gt;&lt;/code&gt;. You can chain as many parameters as you want, although you will run into issues if some are required and some are not (what if the first parameter is optional, but the second isn’t?) It’s better to send multiple fields as URL parameters or body data.&lt;/p&gt;

&lt;p&gt;If you do want to add a parameter as part of the endpoint, you do that to the &lt;code&gt;$route&lt;/code&gt; argument in your &lt;code&gt;register_rest_route&lt;/code&gt;function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;\d+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ADDED ID HERE&lt;/span&gt;
        &lt;span class="c1"&gt;// ...args&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The argument is wrapped in a regular expression, so let’s break it down:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'(?P&amp;lt;id&amp;gt;\\d+)'&lt;/span&gt; &lt;span class="c1"&gt;// the full argument (parathenses are to group it)&lt;/span&gt;
&lt;span class="s1"&gt;'?P'&lt;/span&gt; &lt;span class="c1"&gt;// denotes that this is a parameter&lt;/span&gt;
&lt;span class="s1"&gt;'&amp;lt;id&amp;gt;'&lt;/span&gt; &lt;span class="c1"&gt;// the name of the parameter&lt;/span&gt;
&lt;span class="s1"&gt;'\\d+'&lt;/span&gt; &lt;span class="c1"&gt;// indicates the paramter should be an integer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While this is hard to read, it does make sure the parameter is defined and has to be an integer. This change means the following calls are either valid or invalid:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ndx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="c1"&gt;// not valid (missing the parameter)&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ndx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// valid&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;wp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ndx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="c1"&gt;// not valid (strings are not allowed)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To access the parameter in your callback function, just use &lt;code&gt;get_param&lt;/code&gt; like before:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;What if you wanted to make the parameter completely optional, like how WordPress does for posts? Just make a new route! Here’s the full code with our routes we created before the example above, plus our new one:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rest_api_init'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'register_your_routes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register_your_routes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EDITABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'another_callback_function'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// our new route&lt;/span&gt;
    &lt;span class="nf"&gt;register_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'ndx/v1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'my-endpoint/(?P&amp;lt;id&amp;gt;\d+)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'methods'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;READABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'callback_function_with_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'permission_callback'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'__return_true'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;You are now ready to start creating your own routes! In our next article, we will go over the security features of &lt;code&gt;register_rest_route&lt;/code&gt; like custom permissions, sanitizing data, and validating passed-in parameters, so you can create routes for real-world use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628430%2Fd32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>php</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Using Postman with the WordPress REST API</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Thu, 26 Aug 2021 15:23:03 +0000</pubDate>
      <link>https://dev.to/david_woolf/using-postman-with-the-wordpress-rest-api-41bk</link>
      <guid>https://dev.to/david_woolf/using-postman-with-the-wordpress-rest-api-41bk</guid>
      <description>&lt;p&gt;Postman is a powerful tool to send URL requests and view the response data back. While you can do public GET requests in any browser, Postman offers the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POST, PUT, and DELETE requests (along with a bunch more)&lt;/li&gt;
&lt;li&gt;Passing headers&lt;/li&gt;
&lt;li&gt;Passing body data&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Viewing the response as different types of data&lt;/li&gt;
&lt;li&gt;Saving your responses for use later&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sending your first request
&lt;/h2&gt;

&lt;p&gt;First, make sure you download and install the Postman app from &lt;a href="https://www.postman.com/downloads/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. We'll be using the desktop version to walk through making requests and viewing the results.&lt;/p&gt;

&lt;p&gt;Once the app is installed, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08hnlr15f3za2u117rqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08hnlr15f3za2u117rqg.png" alt="Screen shot of Postman with no configuration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To start making requests, just click the + icon next to the Overview tab in the main column.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft05y8jwabff02ztp6wji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft05y8jwabff02ztp6wji.png" alt="Screen shot of Postman with a new request tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the top area of the new tab, you have a few options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set the request type (defaults to GET)&lt;/li&gt;
&lt;li&gt;enter your url&lt;/li&gt;
&lt;li&gt;send the request&lt;/li&gt;
&lt;li&gt;Add url parameters, authorization, headers, and body data (we will not be covering the other  options in this article)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fastest way to get started is to test a public GET request. Whether you're working locally or with a live site, you can enter your WordPress site's url and append &lt;code&gt;/wp-json/wp/v2/posts&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;

With permalinks: &lt;span class="gs"&gt;**http://index.local/wp-json/wp/v2/posts**&lt;/span&gt;
Without permalinks: &lt;span class="gs"&gt;**http://index.local/?rest_route=/wp/v2/posts**&lt;/span&gt;&lt;span class="sb"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Once you enter the url, hit "Send" and you'll see the response at the bottom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28oo3gvq3lgb12bg2fi0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28oo3gvq3lgb12bg2fi0.png" alt="Screen shot of Postman with a GET request and the resulting JSON value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Postman does a few things here that are useful for testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Displays the body response and formats the response automatically as JSON&lt;/li&gt;
&lt;li&gt;Provides other views like raw (this is super helpful when using print_r to debug)&lt;/li&gt;
&lt;li&gt;Has options to view any cookies in the request, and the headers that were sent back&lt;/li&gt;
&lt;li&gt;Provides the status, time the response took, and the size&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sending POST requests
&lt;/h2&gt;

&lt;p&gt;To send POST (or PUT and DELETE requests) from Postman to WordPress, we'll need to authenticate our requests. This is a WordPress requirement as these types of requests need to happen when logged in.&lt;/p&gt;

&lt;p&gt;There are a couple different ways to authenticate requests from Postman to WordPress.&lt;/p&gt;
&lt;h3&gt;
  
  
  Passing a nonce and cookie
&lt;/h3&gt;

&lt;p&gt;If you are actively working in the WordPress dashboard and need to quickly test some API methods in Postman, you can actually pass your browser's nonce and cookie values in Postman.&lt;/p&gt;

&lt;p&gt;This requires that you perform an action that sends the API request, which you will then read from the browser's inspector tools. &lt;/p&gt;

&lt;p&gt;From any modern browser:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open up the browser's inspector tools&lt;/li&gt;
&lt;li&gt;Click the Network tab&lt;/li&gt;
&lt;li&gt;Filter to show only Fetch or XHR requests&lt;/li&gt;
&lt;li&gt;Refresh the page (or perform an action that will cause an API request)&lt;/li&gt;
&lt;li&gt;Click the request from the list in the inspector&lt;/li&gt;
&lt;li&gt;Click the Headers tab&lt;/li&gt;
&lt;li&gt;Find the request headers&lt;/li&gt;
&lt;li&gt;copy the X-WP-Nonce header value&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then in your Postman request tab:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the Headers tab at the top, under the url bar&lt;/li&gt;
&lt;li&gt;Scroll to the bottom of the list and double click the key field to make it editable&lt;/li&gt;
&lt;li&gt;Enter X-WP-Nonce&lt;/li&gt;
&lt;li&gt;Double click the value field next to the key field&lt;/li&gt;
&lt;li&gt;Enter your nonce value&lt;/li&gt;
&lt;li&gt;Enter another header and name it Cookie&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now go back to your browser's inspector tools&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find your cookies list

&lt;ol&gt;
&lt;li&gt;Safari: Click Storage at the top, and then Cookies in the sidebar&lt;/li&gt;
&lt;li&gt;Chrome: Click Application at the top, then open the Cookies dropdown in the sidebar and select the site you are on&lt;/li&gt;
&lt;li&gt;Firefox: Click Storage at the top, then open the Cookies dropdown in the sidebar and select the site you are on&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Find the cookie starting with wordpress_logged_in&lt;/li&gt;
&lt;li&gt;Copy the full cookie name and paste it into the value for the Cookie header in Postman&lt;/li&gt;
&lt;li&gt;Add an = sign at the end&lt;/li&gt;
&lt;li&gt;Copy the full cookie value from the browser and enter if after the = sign&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you're done, you will see two new headers that look something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;X-WP-Nonce | ce243bbe44&lt;/li&gt;
&lt;li&gt;Cookie | wordpress_logged_in_9ab7178f511b0215ddb4f12594ea7d1b=david%7C1629648436%7CKRHVjvhnwKGvUxs6lUQ6PyaPiAgi6TfwjUGwalhCQm2%7C5948f6d8ebad2bbaab3984c1876020217d6a6e9db6b90dcdda9e10c0967d6182&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, it's a lot of steps. But if you are working in a system where you can't add extra authentication and need to test a POST endpoint, it can be valuable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Basic authentication with application passwords
&lt;/h3&gt;

&lt;p&gt;Using basic authentication is a much easier way to authenticate requests if you have the option. It also lets you perform more powerful testing, as you could try requests as different users with varying roles to make sure your APIs are secure.&lt;/p&gt;

&lt;p&gt;WordPress now comes with an application password generator for users, making basic auth easy to setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit the user in WordPress you want to authenticate as&lt;/li&gt;
&lt;li&gt;Scroll down to Application Passwords&lt;/li&gt;
&lt;li&gt;Enter Postman in the "New Application Password Name"&lt;/li&gt;
&lt;li&gt;Click "Add New Application Password"&lt;/li&gt;
&lt;li&gt;The password will be shown and look something like this: &lt;code&gt;jMOs od2z uGji E4Pu oYMV v1HZ&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make sure to copy the password before doing anything else. You can only see it the one time (if you screw up, revoke the password you just made and start over)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In your Postman request screen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click Authorization under the url field&lt;/li&gt;
&lt;li&gt;Select Basic Auth from the type dropdown&lt;/li&gt;
&lt;li&gt;Enter your WordPress  username&lt;/li&gt;
&lt;li&gt;Enter the password you copied&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb45se0ccx4a4c7xgvrp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb45se0ccx4a4c7xgvrp5.png" alt="Screen shot of a Postman request tab top area"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are now setup to handle POST, PUT, and DELETE requests! To test this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change the request dropdown next to the url to POST&lt;/li&gt;
&lt;li&gt;Enter your URL plus &lt;code&gt;/wp-json/wp/v2/posts/&amp;lt;id&amp;gt;&lt;/code&gt; where &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt; is a post ID&lt;/li&gt;
&lt;li&gt;Select the Body tab under the url field&lt;/li&gt;
&lt;li&gt;Select the raw radio option&lt;/li&gt;
&lt;li&gt;Change the Text dropdown on the right of the radio options to be &lt;strong&gt;JSON&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter: &lt;code&gt;{ "title": "New Title" }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click Send&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you follow these steps, you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3ayn1jpsts642sl785x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3ayn1jpsts642sl785x.png" alt="Postman request tab with body settings selected"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding authentication for multiple requests
&lt;/h3&gt;

&lt;p&gt;To make authentication even easier, you should create a collection for your requests, and set the authentication globally. That way you can spin up new requests without copy and pasting your username and password every time. To do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make sure your sidebar in Postman is open and set to Collections:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5po2fuu7nfwzf62b57i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5po2fuu7nfwzf62b57i.png" alt="Postman left hand sidebar with collections"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the Create Collection button in the center&lt;/li&gt;
&lt;li&gt;Your collection will immediately be created and show authentication settings:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcoruxjcyl6d2wudsd0ra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcoruxjcyl6d2wudsd0ra.png" alt="A new collection in Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select Basic Auth and perform the same steps as authenticating a single request:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1xm20ynt91ifdmb949q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1xm20ynt91ifdmb949q.png" alt="Zoomed in screenshot of Basic authentication settings in Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go back to your request tab and revert the Authorization settings back to "Inherit auth from parent" &lt;/li&gt;
&lt;li&gt;Lastly, save your request and add it into the new collection&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;You are now ready to test your WordPress REST endpoints in Postman! With these steps you can quickly test one-off APIs when you don't have access to modify users or create collections for your different WordPress installations using basic authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F628430%2Fd32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Handling Nonces in WordPress</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Mon, 23 Aug 2021 10:00:00 +0000</pubDate>
      <link>https://dev.to/david_woolf/handling-nonces-in-wordpress-37ei</link>
      <guid>https://dev.to/david_woolf/handling-nonces-in-wordpress-37ei</guid>
      <description>&lt;p&gt;WordPress provides an easy to use nonce system to create and verify unique hashes for certain actions. Note that WordPress uses the word nonce to refer to a security token but they aren’t true nonces. Here is how WordPress defines their use of nonce:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WordPress’s security tokens are called “nonces” (despite the above-noted differences from true nonces) because they serve much the same purpose as nonces do. They help protect against several types of attacks including CSRF, but do not protect against replay attacks because they aren’t checked for one-time use. Nonces should never be relied on for authentication, authorization, or access control. Protect your functions using current_user_can(), and always assume nonces can be compromised.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While there are plenty of times that using a nonce is not appropriate, some examples of good use cases for nonces are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clicking a link that would alter the database&lt;/li&gt;
&lt;li&gt;submitting a form that would alter the database&lt;/li&gt;
&lt;li&gt;using WordPress’s REST API to perform POST, PUT, or DELETE actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: a nonce is valid for 24 hours, and is not a one-time use code. This is why WordPress doesn’t consider their version true nonces.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create a nonce
&lt;/h2&gt;

&lt;p&gt;There are a couple of ways to create nonces in WordPress, depending on where you are placing the nonce:&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate a nonce code by itself
&lt;/h3&gt;

&lt;p&gt;The most basic option is &lt;code&gt;wp_create_nonce&lt;/code&gt; which will give you the nonce value. I find this useful for passing a nonce to a REST API endpoint as a header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_create_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// can be a string or integer&lt;/span&gt;

&lt;span class="c1"&gt;// example:&lt;/span&gt;
&lt;span class="nv"&gt;$nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_create_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'trash-post-23'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// outputs: 5817bdf2ac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Generate a url with a nonce parameter
&lt;/h3&gt;

&lt;p&gt;Next, we have wp_nonce_url which takes a base URL, the nonce action name, and the name of the parameter (defaults to _wpnonce). This will return a full URL with the nonce appended as a URL parameter&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$url_with_nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_nonce_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// example: &lt;/span&gt;
&lt;span class="nv"&gt;$url_with_nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_nonce_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;https://localhost&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'trash-post-23'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'_wpnonce'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// outputs: &amp;lt;https://localhost?_wpnonce=5817bdf2ac&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Generate a hidden input with a nonce name and value
&lt;/h3&gt;

&lt;p&gt;Finally, we have wp_nonce_field which is a quick way to output a hidden field with the nonce value. It also will add the referrer URL so you can verify the user came from the previous page and has a valid nonce.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;wp_nonce_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$referer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$echo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// example:&lt;/span&gt;
&lt;span class="nf"&gt;wp_nonce_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'trash-post-23'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// outputs: &lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;input type="hidden" id="_wpnonce" name="_wpnonce" value="5817bdf2ac"&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;input type="hidden" name="_wp_http_referer" value="/wp-admin/plugins.php?plugin_status=all&amp;amp;amp;paged=1&amp;amp;amp;s"&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  How to verify a nonce
&lt;/h2&gt;

&lt;p&gt;When working inside the WordPress dashboard, you can quickly verify a nonce and referrer by calling &lt;code&gt;check_admin_referer&lt;/code&gt;. By default, you need to pass in the action name. If you changed the nonce parameter name (defaults to &lt;code&gt;_wpnonce&lt;/code&gt;), you can pass that in as a second parameter&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;check_admin_referer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// example: &lt;/span&gt;
&lt;span class="nf"&gt;check_admin_referer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'trash-post-23'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When working with async requests, you have a couple of options:&lt;/p&gt;
&lt;h3&gt;
  
  
  check_ajax_referer
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;check_ajax_referer&lt;/code&gt; function will handle verification and stop processing the request&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;check_ajax_referer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// example:&lt;/span&gt;
&lt;span class="nf"&gt;check_ajax_referer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'trash-post-23'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  wp_verify_nonce
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;wp_verify_nonce&lt;/code&gt; function will handle verification but it is up to you to return an error. It’s recommended to return a 403: Forbidden error.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;wp_verify_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$nonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// example:&lt;/span&gt;
&lt;span class="nf"&gt;wp_verify_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'5817bdf2ac'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'trash-post-23'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// the nonce itself would be passed to the request and verified from the body or parameter list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Using nonces with REST API requests
&lt;/h2&gt;

&lt;p&gt;If you are creating your own API requests in WordPress (for example: with fetch) and you want to submit requests using POST, PUT, or DELETE, then you will have to pass a nonce value. Fortunately, this is pretty easy if you are enqueuing your javascript files correctly.&lt;/p&gt;

&lt;p&gt;When using &lt;code&gt;wp_enqueue_script&lt;/code&gt; you can pass another function called &lt;code&gt;wp_localize_script&lt;/code&gt; with any data you want to be accessible from that file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;wp_enqueue_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx-script'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;wp_localize_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx-script'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="s1"&gt;'wp_api'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'nonce'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;wp_create_nonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'wp_rest'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Basically, you reference the name of your enqueued script, set your own variable name to use in javascript, and then pass an array of options. This will then provide you a global object in javascript. Here is how you would use the nonce in a fetch statement&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-WP-Nonce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wp_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nonce&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something here&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The only important part of this is the headers option in the second parameter of the fetch statement, passing the nonce. Custom headers always start with &lt;code&gt;X&lt;/code&gt; and then &lt;code&gt;WP-Nonce&lt;/code&gt; is defined by WordPress itself and what they’ll look for.&lt;/p&gt;

&lt;p&gt;What’s great about this pattern is that you don’t need to verify the nonce in your rest endpoint. The system takes care of that for you and will return a 403: Forbidden error if you try to submit something without a nonce&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: publicly consumable API&lt;/em&gt; endpoints do not require this which is why you can fetch a list of posts right from your browser in the URL &lt;em&gt;field.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrap up (and a note on security)
&lt;/h2&gt;

&lt;p&gt;Once again, it’s important to note that nonces should not be used in place of proper authentication. They are simply an extra check to prevent authenticated users from performing an action they didn’t intend to.&lt;/p&gt;

&lt;p&gt;With the REST API especially, the nonce example here is only for requests sent while a user is logged in, and your endpoints should also use the permissions callback to check if the current user can perform the intended action.&lt;/p&gt;

&lt;p&gt;I would also recommend you use the nonce functions that take care of some of the heavy lifting for you (like creating and verifying hidden fields with the nonce value).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Author&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
  
    .ltag__user__id__628430 .follow-action-button {
      background-color: #000000 !important;
      color: #ffffff !important;
      border-color: #000000 !important;
    }
  
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5srIcvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--zYYDI4-z--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/628430/d32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>php</category>
      <category>security</category>
    </item>
    <item>
      <title>Function breakdown: rest_ensure_response</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Thu, 19 Aug 2021 16:33:58 +0000</pubDate>
      <link>https://dev.to/david_woolf/function-breakdown-restensureresponse-21m9</link>
      <guid>https://dev.to/david_woolf/function-breakdown-restensureresponse-21m9</guid>
      <description>&lt;p&gt;When making your own routes with the WordPress REST API, you have to return a valid REST object. WordPress provides a couple of ways to do this, including the rest_ensure_response function. When working with REST APIs in Javascript you will see this a lot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rest-endpoint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// ...do something with the data here)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first method on the fetch function is passed the response object, which then returns the request's body. The second method is then passed that request body as JSON.&lt;/p&gt;

&lt;p&gt;This pattern is possible because the data from the API is returned properly. Read on to see how the &lt;code&gt;rest_ensure_response&lt;/code&gt; function works and how you can use it in your own routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function definition
&lt;/h2&gt;

&lt;p&gt;The WordPress code reference &lt;a href="https://developer.wordpress.org/reference/functions/rest_ensure_response/"&gt;describes&lt;/a&gt; &lt;code&gt;rest_ensure_response&lt;/code&gt; as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[rest_ensure_response] implements WP_REST_Response, allowing usage of set_status/header/etc without needing to double-check the object. Will also allow WP_Error to indicate error responses, so users should immediately check for this value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The documentation states that the function takes one parameter, which can be multiple types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// you normally return the result from a rest route&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// return one of:&lt;/span&gt;
    &lt;span class="c1"&gt;// WP_REST_Response&lt;/span&gt;
    &lt;span class="c1"&gt;// WP_HTTP_Response&lt;/span&gt;
  &lt;span class="c1"&gt;// WP_Error&lt;/span&gt;
    &lt;span class="c1"&gt;// ?... (mixed content)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can return a &lt;code&gt;WP_REST_Response&lt;/code&gt; class, &lt;code&gt;WP_HTTP_Response&lt;/code&gt; class, &lt;code&gt;WP_Error class&lt;/code&gt;, or mixed content. Let's review the function definition, see how it works, and what it returns.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: mixed content just refers to different types of data: arrays, object, strings, booleans, integers, etc.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Return value of the function
&lt;/h2&gt;

&lt;p&gt;Here is the function definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// location: wp-includes/rest-api.php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;is_wp_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="n"&gt;WP_REST_Response&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// While WP_HTTP_Response is the base class of WP_REST_Response, it doesn't provide&lt;/span&gt;
  &lt;span class="c1"&gt;// all the required methods used in WP_REST_Server::dispatch().&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="n"&gt;WP_HTTP_Response&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WP_REST_Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_status&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;get_headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WP_REST_Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, the function checks if the passed in value &lt;code&gt;$response&lt;/code&gt; is a &lt;code&gt;WP_Error&lt;/code&gt; and if so, it returns it immediately.&lt;/p&gt;

&lt;p&gt;Next, it checks if the passed-in value is a &lt;code&gt;WP_REST_Response&lt;/code&gt; instance and if so, returns it directly. Otherwise, if the value is a &lt;code&gt;WP_HTTP_Response&lt;/code&gt; instance, it returns it as a &lt;code&gt;WP_REST_Response&lt;/code&gt; and passes the data, status, and headers to the class.&lt;/p&gt;

&lt;p&gt;If all else fails, the function defaults to returning the value as a &lt;code&gt;WP_REST_Response&lt;/code&gt; instance. All of this is to say, it's either going to return a &lt;code&gt;WP_Error&lt;/code&gt; or &lt;code&gt;WP_Rest_Response&lt;/code&gt; instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll normally pass to the function (aka: mixed content)
&lt;/h2&gt;

&lt;p&gt;In your own code, you'll probably be passing in mixed content (your data) to &lt;code&gt;rest_ensure_response&lt;/code&gt;. End users are usually returning &lt;code&gt;rest_ensure_response&lt;/code&gt; from a custom &lt;code&gt;register_rest_route&lt;/code&gt; and passing back either an error or valid data.&lt;/p&gt;

&lt;p&gt;Here's a simple example of &lt;code&gt;rest_ensure_response&lt;/code&gt; in a custom route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;callback_for_custom_rest_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WP_Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'missing_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'please provide your name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// if name is set, return a 200 OK with the string value passed in for name&lt;/span&gt;
    &lt;span class="c1"&gt;// if name is not set, return a 500 Internal Server Error with error information defined above&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;rest_ensure_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all you need to use &lt;code&gt;rest_ensure_response&lt;/code&gt;!&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>rest</category>
      <category>api</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to get started with WordPress Hooks in Javascript</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Tue, 17 Aug 2021 15:54:33 +0000</pubDate>
      <link>https://dev.to/david_woolf/how-to-get-started-with-wordpress-hooks-in-javascript-400o</link>
      <guid>https://dev.to/david_woolf/how-to-get-started-with-wordpress-hooks-in-javascript-400o</guid>
      <description>&lt;p&gt;WordPress has provided hooks in PHP for years and they recently released a version for Javascript. Hooks allow different parts of your code to augment values or perform additional actions. When referring to actions and filters, we'll be using the term "hooks" to discuss both. If you see the words "action" or "filter", assume we're discussing functionality that only relates to only that hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to start using WordPress hooks in Javascript
&lt;/h2&gt;

&lt;p&gt;Before handing WordPress hooks in Javascript, make sure you are coding in a JS file that has access to the global &lt;code&gt;wp&lt;/code&gt; javascript variable, or that you are using the &lt;code&gt;@wordpress/hooks&lt;/code&gt; npm package&lt;/p&gt;

&lt;p&gt;This article will be using the wp global variables hook endpoints for coding examples. If you are enqueuing your javascript correctly in WordPress, you should already have access to this variable. You can confirm this by doing &lt;code&gt;console.log(wp.hooks)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding your own hooks
&lt;/h2&gt;

&lt;p&gt;Adding actions and filters in Javascript is similar to PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// actions&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hookName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;namespace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// filters&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hookName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;namespace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameters for both hook types are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;hookName&lt;/strong&gt;: the name of your action or filter, which you'll use to call the hook&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;namespace&lt;/strong&gt;: a custom namespace (for example: your product name).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;callback&lt;/strong&gt;: the function that will execute your hook &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;priority&lt;/strong&gt;: the order in which your hook fires&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not sure why the namespace parameter exists because you don't use it when calling a hook (although you do when removing one). To prevent duplicate hook names, I would recommend adding a namespace to your hook name as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying hooks in your code
&lt;/h2&gt;

&lt;p&gt;Just like with PHP, you have access to a couple of functions to call your filters and actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// actions&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hookName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// filters&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;applyFilters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hookName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we don't refer to the namespace here, which is why I recommend adding one to your hook name.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Reminder: filters take a default value before the args list, and should return a value to a variable. Actions should execute code and not return anything.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With these four API methods, you can implement a Javascript version of WordPress's hooks system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting when hooks don't fire in the correct order
&lt;/h2&gt;

&lt;p&gt;An issue I ran into the first time I tried to use the &lt;code&gt;wp.hooks.addFilter&lt;/code&gt; method was inconsistent filter execution.&lt;/p&gt;

&lt;p&gt;I was trying to pass a string through two &lt;code&gt;addFilter&lt;/code&gt; calls in separate plugins and I wanted the end value to include any modifications in each callback. Here is how I enqueued my javascript files in PHP (split between two plugin.php files):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// first plugin&lt;/span&gt;
&lt;span class="nf"&gt;wp_enqueue_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx-first-plugin-script'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'dist/js/first.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;[],&lt;/span&gt; 
    &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// second plugin&lt;/span&gt;
&lt;span class="nf"&gt;wp_enqueue_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx-second-plugin-script'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'dist/js/second.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;[],&lt;/span&gt;
     &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my first.js file I created a filter that would return "I am the beginning" prepended to a passed in value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ndx-first-plugin-script (first.js)&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ndx_change_string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`I am the beginning. &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my second.js file, I added the same filter hook with a higher (read: lesser) priority and appended "I am the end" to the passed-in value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ndx-second-plugin-script (second.js)&lt;/span&gt;
&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ndx_change_string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; I am the end.`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;applyFilters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ndx_change_string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because my apply calls passed in empty strings I expected the result: "I am the beginning. I am the end." but what I got was "I am the end."&lt;/p&gt;

&lt;p&gt;Unfortunately, my second plugin's javascript loads first and doesn't see the first plugin's filter value (this can happen in PHP too, by the way). You will generally use filters to augment a standalone value, but it's also common to use them to add and remove items from arrays so sometimes the order is important.&lt;/p&gt;

&lt;p&gt;There are a couple of ways to solve this problem:&lt;/p&gt;

&lt;p&gt;Ensure the plugin where you plan to call &lt;code&gt;applyFilters&lt;/code&gt; is enqueued as a dependency in your other scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// second plugin&lt;/span&gt;
&lt;span class="nf"&gt;wp_enqueue_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'ndx-second-plugin-script'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'dist/js/second.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ndx-first-plugin-script'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// add your first plugin script as a required dependency&lt;/span&gt;
    &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or utilize the built-in &lt;code&gt;hookAdded&lt;/code&gt; method to call additional filters after the first one is created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hookAdded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;core/i18n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ndx_change_string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="c1"&gt;// add additional filters here after the first one fires&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;hookAdded&lt;/code&gt; method can be fragile and buggy and it would be very easy to get stuck in an infinite loop if two addFilter calls had a priority of 10.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>javascript</category>
    </item>
    <item>
      <title>WordPress REST API: Delete method returns an error</title>
      <dc:creator>David Woolf</dc:creator>
      <pubDate>Mon, 26 Apr 2021 16:31:58 +0000</pubDate>
      <link>https://dev.to/david_woolf/wordpress-rest-api-delete-method-returns-an-error-3m3n</link>
      <guid>https://dev.to/david_woolf/wordpress-rest-api-delete-method-returns-an-error-3m3n</guid>
      <description>&lt;p&gt;WordPress provides &lt;code&gt;GET, POST, PUT,&lt;/code&gt;and&lt;code&gt;DELETE&lt;/code&gt; methods for a variety of content. In Index, we use the &lt;code&gt;/post/&amp;lt;id&amp;gt;&lt;/code&gt; endpoint with the &lt;code&gt;DELETE&lt;/code&gt; method to trash posts when a user clicks delete. This seemed pretty straightforward, but during testing we ran into a problem: our posts were not being deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem we ran into with DELETE
&lt;/h2&gt;

&lt;p&gt;Every time we introduce a new feature to &lt;a href="https://indexforwp.com/"&gt;Index&lt;/a&gt;, or install it on a new machine, we do a few commands to make sure the core experience of the plugin is intact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select and edit posts&lt;/li&gt;
&lt;li&gt;Select and trash posts&lt;/li&gt;
&lt;li&gt;Permanently Delete some trashed posts&lt;/li&gt;
&lt;li&gt;Restore some trashed posts&lt;/li&gt;
&lt;li&gt;Attempt all the above with a user role that can’t do it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Around December of last year, we started using &lt;a href="https://localwp.com"&gt;Local&lt;/a&gt; for all local WordPress development. When we switched, we did the above steps. Everything worked great, except when we tried to trash posts. No matter what post we tried to delete, we would receive an unauthorized error, and the post was never removed. We double checked that our role should be able to delete posts, and once we confirmed that, we opened up the Postman app and tested some other api requests that require authentication. All of those were working, so why couldn’t we delete a post?&lt;/p&gt;

&lt;p&gt;Next, we tried was removing a post from the Gutenberg editor. That worked, so clearly there wasn’t some unfixable issue with the web server. So we opened up our web inspector, reviewed the network requests and discovered that WordPress was using the same &lt;code&gt;post/&amp;lt;id&amp;gt;&lt;/code&gt; endpoint, but it was using &lt;code&gt;POST&lt;/code&gt; instead of &lt;code&gt;DELETE&lt;/code&gt; for the method.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution to deleting posts using the WordPress API
&lt;/h2&gt;

&lt;p&gt;After some digging, we found that Local uses nginx as a web server and only has the &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; methods enabled for api requests (others like &lt;code&gt;PUT&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; are not enabled). The solution ended up being simple, but might not be obvious to anyone that doesn’t work with APIs every day.&lt;/p&gt;

&lt;p&gt;Send the request with the method set to &lt;code&gt;POST&lt;/code&gt; and add an additional header to your fetch statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-HTTP-Method-Override&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Doing this ensures broader support for different hosting environments that may not have methods other than GET and POST enabled. Nothing has to happen on the PHP side, and if you are making your own endpoints with &lt;code&gt;register_rest_route&lt;/code&gt;, you can keep setting up your methods per the WordPress documentation website.&lt;/p&gt;
&lt;h2&gt;
  
  
  Author
&lt;/h2&gt;


&lt;div class="ltag__user ltag__user__id__628430"&gt;
  
    .ltag__user__id__628430 .follow-action-button {
      background-color: #000000 !important;
      color: #ffffff !important;
      border-color: #000000 !important;
    }
  
    &lt;a href="/david_woolf" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5srIcvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--zYYDI4-z--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/628430/d32f9df5-f9df-49f3-b543-580283e42caa.jpeg" alt="david_woolf image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/david_woolf"&gt;David Woolf&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/david_woolf"&gt;Designer and developer. Follow me on twitter: https://twitter.com/wwuulf&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>wordpress</category>
      <category>javascript</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
