WordPressJanuary 12, 202611 min read

WordPress REST API: A Complete Guide

Rohit Kumar
Rohit Kumar
React, WordPress & Automation Expert

The WordPress REST API has completely changed what you can do with WordPress. You can now use WordPress as a headless CMS, build mobile apps that connect to your WordPress site, or integrate WordPress with other services. In this guide, I'll show you everything you need to know to master the WordPress REST API.

What is the WordPress REST API?

The REST API is a way for applications to talk to WordPress using HTTP requests. Instead of loading WordPress's PHP templates and themes, you can request data in JSON format and use it however you want - in a React app, mobile app, or any other application.

It's been part of WordPress core since version 4.7, so if you're running a modern WordPress site, the API is already enabled and ready to use. No plugins needed!

Making Your First API Request

Let's start simple. Open your browser and go to yoursite.com/wp-json/wp/v2/posts. You'll see a JSON response with all your published posts. That's it - you just made your first API request!

// Example response structure
{
  "id": 123,
  "date": "2026-01-12T10:00:00",
  "title": {
    "rendered": "My Blog Post"
  },
  "content": {
    "rendered": "<p>Post content here...</p>"
  },
  "excerpt": {
    "rendered": "<p>Brief excerpt...</p>"
  },
  "author": 1,
  "featured_media": 456
}

Understanding API Endpoints

The REST API has different endpoints for different types of content. Here are the most useful ones:

To get a specific post, add the ID: /wp-json/wp/v2/posts/123

Fetching Posts in JavaScript

Let's fetch some posts using JavaScript. Here's a simple example:

async function getPosts() {
  try {
    const response = await fetch(
      'https://yoursite.com/wp-json/wp/v2/posts?per_page=10'
    )
    const posts = await response.json()
    
    posts.forEach(post => {
      console.log(post.title.rendered)
      console.log(post.excerpt.rendered)
    })
  } catch (error) {
    console.error('Error fetching posts:', error)
  }
}

getPosts()

Filtering and Querying Data

The API supports URL parameters to filter results. This is incredibly powerful:

// Get 5 posts per page
/wp-json/wp/v2/posts?per_page=5

// Get page 2
/wp-json/wp/v2/posts?page=2

// Get posts from a specific category (ID 5)
/wp-json/wp/v2/posts?categories=5

// Search posts
/wp-json/wp/v2/posts?search=react

// Order by date descending (newest first)
/wp-json/wp/v2/posts?orderby=date&order=desc

// Get posts by a specific author (ID 2)
/wp-json/wp/v2/posts?author=2

// Combine multiple parameters
/wp-json/wp/v2/posts?per_page=10&categories=5&orderby=date&order=desc

Embedding Related Data

By default, the API returns IDs for related content like authors and featured images. To get full data in one request, use the _embed parameter:

// Get posts with author info and featured images
const response = await fetch(
  'https://yoursite.com/wp-json/wp/v2/posts?_embed'
)

const posts = await response.json()

posts.forEach(post => {
  // Access author name
  const authorName = post._embedded.author[0].name
  
  // Access featured image
  const featuredImage = post._embedded['wp:featuredmedia']?.[0]?.source_url
  
  console.log(post.title.rendered)
  console.log('By:', authorName)
  console.log('Image:', featuredImage)
})
Using _embed reduces the number of API requests you need to make, which improves performance significantly.

Authentication and Creating Content

Reading public data doesn't require authentication, but creating, updating, or deleting content does. WordPress supports several authentication methods:

1. Application Passwords (Easiest)

WordPress 5.6+ includes application passwords. Go to your user profile in WordPress admin, scroll down to "Application Passwords," create a new one, and use it for authentication:

const username = 'your-username'
const appPassword = 'your-app-password'
const credentials = btoa(`${username}:${appPassword}`)

const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Basic ${credentials}`
  },
  body: JSON.stringify({
    title: 'New Post via API',
    content: 'This post was created using the REST API!',
    status: 'publish'
  })
})

2. JWT Authentication (For Apps)

For more secure authentication in apps, use JWT tokens. You'll need a plugin like "JWT Authentication for WP REST API."

Creating a Headless WordPress Site with Next.js

Here's a practical example - building a blog with Next.js and WordPress:

// lib/wordpress.js
const WP_API_URL = 'https://yoursite.com/wp-json/wp/v2'

export async function getPosts(limit = 10) {
  const res = await fetch(
    `${WP_API_URL}/posts?per_page=${limit}&_embed`
  )
  return res.json()
}

export async function getPost(slug) {
  const res = await fetch(
    `${WP_API_URL}/posts?slug=${slug}&_embed`
  )
  const posts = await res.json()
  return posts[0]
}

// app/blog/page.jsx
import { getPosts } from '@/lib/wordpress'

export default async function BlogPage() {
  const posts = await getPosts()
  
  return (
    <div>
      <h1>Blog</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title.rendered}</h2>
          <div dangerouslySetInnerHTML={{ 
            __html: post.excerpt.rendered 
          }} />
          <a href={`/blog/${post.slug}`}>Read More</a>
        </article>
      ))}
    </div>
  )
}

Custom Post Types and Fields

To expose custom post types via the API, register them with show_in_rest:

// In your theme's functions.php
register_post_type('projects', [
  'labels' => [
    'name' => 'Projects',
  ],
  'public' => true,
  'show_in_rest' => true, // This makes it available via API
  'rest_base' => 'projects', // Custom endpoint name
]);

// Now accessible at:
// /wp-json/wp/v2/projects

For custom fields, use Advanced Custom Fields (ACF) plugin with REST API support, or register fields manually:

register_rest_field('post', 'custom_field', [
  'get_callback' => function($post) {
    return get_post_meta($post['id'], 'custom_field', true);
  },
  'schema' => [
    'type' => 'string',
    'context' => ['view', 'edit']
  ]
]);

Handling Pagination

The API returns pagination info in response headers:

const response = await fetch(
  'https://yoursite.com/wp-json/wp/v2/posts?per_page=10'
)

const posts = await response.json()
const totalPages = response.headers.get('X-WP-TotalPages')
const totalPosts = response.headers.get('X-WP-Total')

console.log(`Total pages: ${totalPages}`)
console.log(`Total posts: ${totalPosts}`)

Optimizing API Requests

To improve performance:

// Only get specific fields
/wp-json/wp/v2/posts?_fields=id,title,excerpt,date

// Much smaller response, faster loading!

CORS Issues and Solutions

If you're accessing the API from a different domain, you might hit CORS issues. Add this to your WordPress theme's functions.php:

add_action('rest_api_init', function() {
  remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
  add_filter('rest_pre_serve_request', function($value) {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Credentials: true');
    return $value;
  });
}, 15);
Be careful with CORS - only allow origins you trust, especially for authenticated endpoints.

Creating Custom Endpoints

Sometimes you need custom functionality. Create your own endpoints:

add_action('rest_api_init', function() {
  register_rest_route('my-api/v1', '/popular-posts', [
    'methods' => 'GET',
    'callback' => function() {
      $posts = get_posts([
        'numberposts' => 5,
        'meta_key' => 'views',
        'orderby' => 'meta_value_num',
        'order' => 'DESC'
      ]);
      
      return $posts;
    },
    'permission_callback' => '__return_true'
  ]);
});

// Access at: /wp-json/my-api/v1/popular-posts

Security Best Practices

Keep your API secure:

Final Thoughts

The WordPress REST API opens up endless possibilities. You can build modern JavaScript frameworks on top of WordPress, create mobile apps, integrate with other services, or build headless CMS solutions. The key is understanding the basics and then experimenting with what works for your specific needs.

Start simple - fetch some posts, display them on a page. Then gradually add more complex features like authentication, custom endpoints, and advanced querying. The documentation is comprehensive, and the community is helpful when you get stuck.

Tags:WordPressREST APIHeadless
Share this article:

Related Posts