WordPress REST API Basics for Developers
The WordPress REST API opens WordPress to modern web development practices. Instead of being locked into PHP templates, you can access WordPress content from any application—mobile apps, JavaScript fr...
Introduction
The WordPress REST API opens WordPress to modern web development practices. Instead of being locked into PHP templates, you can access WordPress content from any application—mobile apps, JavaScript frameworks, external websites, or custom dashboards. This guide introduces the REST API fundamentals every developer should know.
What Is the WordPress REST API?
Definition
The WordPress REST API is an interface that allows external applications to interact with WordPress using JSON (JavaScript Object Notation) over HTTP.
What You Can Do
- Read content: Get posts, pages, users, media
- Create content: Add new posts, comments, users
- Update content: Modify existing data
- Delete content: Remove posts, media, etc.
- Custom endpoints: Build your own API routes
Key Concepts
Endpoints: URLs that accept requests Routes: The URL patterns (e.g., /wp/v2/posts) Requests: HTTP methods (GET, POST, PUT, DELETE) Responses: JSON data returned Authentication: Verifying user permissions
API Structure
Base URL
https://yoursite.com/wp-json/
Namespace
Built-in endpoints use wp/v2:
https://yoursite.com/wp-json/wp/v2/
Common Endpoints
| Endpoint | Description |
|---|---|
| /wp/v2/posts | Blog posts |
| /wp/v2/pages | Pages |
| /wp/v2/media | Media items |
| /wp/v2/users | Users |
| /wp/v2/categories | Categories |
| /wp/v2/tags | Tags |
| /wp/v2/comments | Comments |
| /wp/v2/types | Post types |
| /wp/v2/taxonomies | Taxonomies |
Making API Requests
GET Requests (Read Data)
Get all posts:
GET https://yoursite.com/wp-json/wp/v2/posts
Get specific post:
GET https://yoursite.com/wp-json/wp/v2/posts/123
With parameters:
GET https://yoursite.com/wp-json/wp/v2/posts?per_page=5&orderby=date
Using JavaScript (Fetch)
// Get posts
fetch('https://yoursite.com/wp-json/wp/v2/posts')
.then(response => response.json())
.then(posts => {
posts.forEach(post => {
console.log(post.title.rendered);
});
});
// With parameters
fetch('https://yoursite.com/wp-json/wp/v2/posts?per_page=5&categories=10')
.then(response => response.json())
.then(posts => console.log(posts));
Using jQuery
$.ajax({
url: 'https://yoursite.com/wp-json/wp/v2/posts',
method: 'GET',
success: function(data) {
console.log(data);
}
});
Using PHP (wp_remote_get)
$response = wp_remote_get('https://yoursite.com/wp-json/wp/v2/posts');
$posts = json_decode(wp_remote_retrieve_body($response));
foreach ($posts as $post) {
echo $post->title->rendered;
}
Common Parameters
Pagination
?per_page=10 // Items per page (max 100)
?page=2 // Page number
?offset=5 // Skip items
Ordering
?orderby=date // date, id, title, slug, modified
?order=desc // asc or desc
Filtering
?search=keyword // Search content
?categories=5,10 // Filter by category IDs
?tags=3,7 // Filter by tag IDs
?author=1 // Filter by author ID
?status=publish // post status
?before=2025-01-01 // Before date
?after=2024-01-01 // After date
Selecting Fields
?_fields=id,title,link // Only return specific fields
Embedding
?_embed // Include related data (author, featured media)
Response Structure
Post Response Example
{
"id": 123,
"date": "2025-01-15T10:30:00",
"date_gmt": "2025-01-15T10:30:00",
"guid": {
"rendered": "https://yoursite.com/?p=123"
},
"modified": "2025-01-15T12:00:00",
"slug": "my-post-title",
"status": "publish",
"type": "post",
"link": "https://yoursite.com/my-post-title/",
"title": {
"rendered": "My Post Title"
},
"content": {
"rendered": "<p>Post content here...</p>",
"protected": false
},
"excerpt": {
"rendered": "<p>Post excerpt...</p>",
"protected": false
},
"author": 1,
"featured_media": 456,
"categories": [5, 10],
"tags": [3, 7]
}
Response Headers
Important headers to check:
X-WP-Total: Total items availableX-WP-TotalPages: Total pages availableLink: Pagination links
Authentication
When Authentication Is Required
No auth needed:
- Reading public posts/pages
- Getting public user info
- Accessing public custom endpoints
Auth required:
- Creating/updating/deleting content
- Accessing private content
- User management
Application Passwords (Recommended)
WordPress 5.6+ includes Application Passwords:
- Go to Users > Your Profile
- Scroll to "Application Passwords"
- Enter application name
- Click "Add New Application Password"
- Copy the password (shown once)
Usage:
const credentials = btoa('username:application_password');
fetch('https://yoursite.com/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + credentials,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'New Post',
content: 'Post content here',
status: 'publish'
})
});
Cookie Authentication
For logged-in users making requests from WordPress:
// Nonce is required (provided by WordPress)
fetch('https://yoursite.com/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'X-WP-Nonce': wpApiSettings.nonce,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'New Post',
status: 'draft'
})
});
Creating, Updating, and Deleting
Create Post (POST)
fetch('https://yoursite.com/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa('user:app_password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'New Post Title',
content: 'Post content goes here',
status: 'publish',
categories: [5],
tags: [3, 7]
})
})
.then(response => response.json())
.then(post => console.log('Created:', post.id));
Update Post (PUT/POST)
fetch('https://yoursite.com/wp-json/wp/v2/posts/123', {
method: 'POST', // or PUT
headers: {
'Authorization': 'Basic ' + btoa('user:app_password'),
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Updated Title'
})
})
.then(response => response.json())
.then(post => console.log('Updated:', post.title.rendered));
Delete Post (DELETE)
fetch('https://yoursite.com/wp-json/wp/v2/posts/123', {
method: 'DELETE',
headers: {
'Authorization': 'Basic ' + btoa('user:app_password')
}
})
.then(response => response.json())
.then(result => console.log('Deleted'));
// Force delete (bypass trash)
fetch('https://yoursite.com/wp-json/wp/v2/posts/123?force=true', {
method: 'DELETE',
headers: {
'Authorization': 'Basic ' + btoa('user:app_password')
}
});
Creating Custom Endpoints
Register Custom Route
add_action('rest_api_init', function() {
register_rest_route('myplugin/v1', '/featured-posts', array(
'methods' => 'GET',
'callback' => 'get_featured_posts',
'permission_callback' => '__return_true'
));
});
function get_featured_posts($request) {
$posts = get_posts(array(
'meta_key' => 'featured',
'meta_value' => '1',
'numberposts' => 5
));
$data = array();
foreach ($posts as $post) {
$data[] = array(
'id' => $post->ID,
'title' => $post->post_title,
'link' => get_permalink($post->ID)
);
}
return new WP_REST_Response($data, 200);
}
Access:
GET https://yoursite.com/wp-json/myplugin/v1/featured-posts
With Parameters
register_rest_route('myplugin/v1', '/posts/(?P<category>\d+)', array(
'methods' => 'GET',
'callback' => 'get_posts_by_category',
'permission_callback' => '__return_true',
'args' => array(
'category' => array(
'validate_callback' => function($param) {
return is_numeric($param);
}
)
)
));
function get_posts_by_category($request) {
$category = $request['category'];
// Your logic here
return new WP_REST_Response($data, 200);
}
Headless WordPress
What Is Headless WordPress?
Using WordPress only as a content management backend, with a separate frontend:
Frontend Options:
- React
- Vue.js
- Next.js
- Gatsby
- Nuxt.js
Benefits
- Modern development stack
- Better performance (static generation)
- Flexible hosting
- Enhanced security
- Better developer experience
Considerations
- Lose some WordPress features
- More complex setup
- SEO requires attention
- Plugin compatibility varies
Best Practices
Performance
// Only request needed fields
fetch('/wp-json/wp/v2/posts?_fields=id,title,link')
// Cache responses
const cache = new Map();
async function getPosts() {
if (cache.has('posts')) {
return cache.get('posts');
}
const posts = await fetch('/wp-json/wp/v2/posts').then(r => r.json());
cache.set('posts', posts);
return posts;
}
Error Handling
fetch('/wp-json/wp/v2/posts')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Security
- Use HTTPS always
- Validate/sanitize input
- Implement rate limiting
- Use proper authentication
- Don't expose sensitive data
Frequently Asked Questions
Is the REST API enabled by default?
Yes, since WordPress 4.7. You can restrict access with plugins if needed.
Can I disable the REST API?
You can restrict or disable it with plugins like "Disable REST API," but this may break some functionality.
How do I add custom fields to API responses?
add_action('rest_api_init', function() {
register_rest_field('post', 'custom_field', array(
'get_callback' => function($post) {
return get_post_meta($post['id'], 'custom_field', true);
}
));
});
Does ACF data appear in API?
Not by default. Use "ACF to REST API" plugin or register fields manually.
What about rate limiting?
WordPress doesn't include rate limiting. Implement at server level or use security plugins.
Key Takeaways
- REST API enables WordPress as a backend for any application
- JSON responses work with any programming language
- Authentication required for writing data
- Custom endpoints extend API capabilities
- Headless WordPress is powerful but adds complexity
- Performance and security require attention
Next Steps
Start by exploring your site's API at /wp-json/. Build a simple JavaScript app that displays posts. Then explore our Headless WordPress guide for advanced implementations.
Meta Description: Learn WordPress REST API basics for developers. Covers endpoints, authentication, CRUD operations, custom routes, and headless WordPress concepts.
Keywords: wordpress rest api, api development, headless wordpress, wordpress json api, wordpress api tutorial
Frequently Asked Questions
Find answers to common questions about this topic
Related Articles
Continue reading with these related posts