WP Manifestindependent plugin directory
manifest / integrations / create-custom-api-in-wordpress

Custom REST API Builder

WordPress plugin that allows you to create fully customizable REST API endpoints

by dadashzadeh · github.com/dadashzadeh/create-custom-api-in-wordpress · website

1stars
1forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/dadashzadeh/create-custom-api-in-wordpress/archive/refs/heads/main.zip

Readme

Custom REST API Builder

A powerful WordPress plugin that allows you to create fully customizable REST API endpoints for your posts, custom post types, and taxonomies with complete CRUD operations and API key authentication.


Description

Custom REST API Builder (CRAB) gives you complete control over your WordPress REST API. Unlike the default WordPress REST API, this plugin lets you choose exactly which fields to expose, in what order, and with granular permission controls.

Key Features

  • 🔧 Fully Customizable Fields - Select and reorder exactly which fields appear in your API responses
  • 🔐 API Key Authentication - Secure your endpoints with API keys and granular permissions
  • 📝 Full CRUD Operations - Create, Read, Update, and Delete posts and terms via API
  • 🎯 Custom Post Type Support - Works with all public post types and taxonomies
  • 🔍 Advanced Filtering - Filter by date, meta fields, taxonomies, and search
  • ACF Compatible - Full support for Advanced Custom Fields
  • 🧪 Built-in API Tester - Test your endpoints directly from the admin panel
  • 📱 Mobile App Ready - Perfect for headless WordPress and mobile applications

Installation

From WordPress Admin

  1. Download the plugin ZIP file
  2. Go to Plugins → Add New → Upload Plugin
  3. Upload the ZIP file and click Install Now
  4. Activate the plugin

Manual Installation

  1. Download and extract the plugin
  2. Upload the custom-rest-api-builder folder to /wp-content/plugins/
  3. Activate the plugin through the Plugins menu in WordPress

Requirements

  • WordPress 4.5 or higher
  • PHP 5.6 or higher

Quick Start

1. Configure Your Fields

  1. Navigate to REST API Builder in your WordPress admin menu
  2. Click on a post type tab (e.g., "Post", "Page")
  3. Check the fields you want to include in API responses
  4. Drag to reorder fields
  5. Click Save All Settings

2. Generate an API Key

  1. Go to the API Keys tab
  2. Enter a name for your key (e.g., "Mobile App")
  3. Select permissions (Read, Write, Delete)
  4. Click Generate API Key
  5. Copy and save the key immediately - it won't be shown again!

3. Make Your First Request

curl -H "X-API-Key: crab_YOUR_API_KEY" \
     https://yoursite.com/wp-json/custom/v1/type/post

API Endpoints

Base URL

https://yoursite.com/wp-json/custom/v1

Posts & Custom Post Types

Method Endpoint Description
GET /type/{post_type} List all items
POST /type/{post_type} Create new item
GET /item/{id} Get single item
PUT /item/{id} Update item
DELETE /item/{id} Delete item
GET /search Search content

Taxonomies

Method Endpoint Description
GET /taxonomy/{taxonomy} List all terms
POST /taxonomy/{taxonomy} Create new term
GET /term/{id} Get single term
PUT /term/{id} Update term
DELETE /term/{id} Delete term

Authentication

API Key Methods

Method 1: HTTP Header (Recommended)

curl -H "X-API-Key: crab_YOUR_API_KEY" \
     https://yoursite.com/wp-json/custom/v1/type/post

Method 2: Query Parameter

https://yoursite.com/wp-json/custom/v1/type/post?api_key=crab_YOUR_API_KEY

Permission Levels

Permission Operations
Read GET requests
Write POST, PUT, PATCH requests
Delete DELETE requests

Authentication Settings

By default, GET requests are public. Enable "Require API Key for Read" in the API Keys tab to require authentication for all requests.


Query Parameters

Collection Endpoints (/type/{post_type})

Parameter Type Default Description
per_page integer 10 Items per page (max 100)
page integer 1 Page number
search string - Search keyword
orderby string date Order by field
order string DESC Sort order (ASC/DESC)
date_after string - Filter posts after date (YYYY-MM-DD)
date_before string - Filter posts before date (YYYY-MM-DD)
meta_key string - Meta key to filter by
meta_value string - Meta value to match
meta_compare string = Comparison operator
tax_query JSON - Taxonomy filter

Taxonomy Endpoints (/taxonomy/{taxonomy})

Parameter Type Default Description
per_page integer 100 Terms per page
page integer 1 Page number
hide_empty boolean false Hide terms with no posts
parent integer - Filter by parent term ID
search string - Search terms

Search Endpoint (/search)

Parameter Type Required Description
q string Yes Search query
post_type string No Limit to specific post type
per_page integer No Results per page
page integer No Page number

Request & Response Examples

Get All Posts

Request:

GET /wp-json/custom/v1/type/post?per_page=10&page=1

Response:

{
  "success": true,
  "post_type": "post",
  "total": 42,
  "total_pages": 5,
  "current_page": 1,
  "per_page": 10,
  "count": 10,
  "items": [
    {
      "id": 123,
      "title": "Hello World",
      "slug": "hello-world",
      "date": "2026-07-20 10:30:00",
      "excerpt": "Welcome to WordPress...",
      "content": "<p>Welcome to WordPress...</p>"
    }
  ]
}

Get Single Item

Request:

GET /wp-json/custom/v1/item/123

Response:

{
  "success": true,
  "item": {
    "id": 123,
    "title": "Hello World",
    "slug": "hello-world",
    "date": "2026-07-20 10:30:00",
    "modified": "2026-07-20 11:00:00",
    "content": "<p>Welcome to WordPress...</p>",
    "featured_image": "https://yoursite.com/wp-content/uploads/image.jpg",
    "meta:custom_field": "Custom value"
  }
}

Create New Post

Request:

POST /wp-json/custom/v1/type/post
Content-Type: application/json
X-API-Key: crab_YOUR_API_KEY

{
  "fields": {
    "post_title": "My New Post",
    "post_content": "<p>This is the content.</p>",
    "post_status": "publish",
    "post_excerpt": "A short summary",
    "meta:custom_field": "Custom value",
    "taxonomies": {
      "category": [1, 5],
      "post_tag": [10, 15]
    },
    "featured_image": 456
  }
}

Response:

{
  "success": true,
  "message": "Item created successfully.",
  "id": 789,
  "item": {
    "id": 789,
    "title": "My New Post",
    "slug": "my-new-post",
    "date": "2026-07-20 11:43:00"
  }
}

Update Existing Post

Request:

PUT /wp-json/custom/v1/item/123
Content-Type: application/json
X-API-Key: crab_YOUR_API_KEY

{
  "fields": {
    "post_title": "Updated Title",
    "meta:price": "99.99"
  }
}

Response:

{
  "success": true,
  "message": "Item updated successfully.",
  "id": 123,
  "updated_fields": ["post_title", "meta:price"],
  "item": {
    "id": 123,
    "title": "Updated Title",
    "modified": "2026-07-20 11:43:00",
    "meta:price": "99.99"
  }
}

Note: Only the fields you send will be updated. All other fields remain unchanged.

Delete Post

Request:

DELETE /wp-json/custom/v1/item/123?force=true
X-API-Key: crab_YOUR_API_KEY

Response:

{
  "success": true,
  "message": "Item permanently deleted.",
  "id": 123
}
Parameter Description
force=false Move to trash (default)
force=true Permanently delete

Advanced Filtering

Filter by Date

GET /wp-json/custom/v1/type/post?date_after=2026-01-01&date_before=2026-12-31

Filter by Meta Field

GET /wp-json/custom/v1/type/product?meta_key=_price&meta_value=100&meta_compare=>=

Available Comparisons: =, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN

Filter by Taxonomy

GET /wp-json/custom/v1/type/post?tax_query=[{"taxonomy":"category","terms":[5,10],"operator":"IN"}]

Tax Query Structure:

[
  {
    "taxonomy": "category",
    "field": "term_id",
    "terms": [5, 10],
    "operator": "IN"
  }
]

Available Fields

Post Fields

Field Key Description
id Post ID
title Post title
slug URL slug
date Publish date
date_gmt Publish date (GMT)
modified Last modified date
modified_gmt Last modified date (GMT)
status Post status
type Post type
excerpt Post excerpt
content Rendered content
content_raw Raw content (no filters)
author_id Author user ID
author_name Author display name
author_email Author email
author_avatar Author avatar URL
featured_image Featured image URL
featured_image_id Featured image attachment ID
featured_image_alt Featured image alt text
featured_image_sizes All image sizes with URLs
permalink Full post URL
parent Parent post ID
menu_order Menu order
comment_count Number of comments
comment_status Comment status
ping_status Ping status
guid Global unique identifier
tax:{taxonomy} Taxonomy terms
meta:{key} Custom meta field
acf:{field} ACF field (if ACF is active)

Taxonomy Term Fields

Field Key Description
term_id Term ID
name Term name
slug Term slug
description Term description
count Post count
parent Parent term ID
taxonomy Taxonomy name
link Term archive URL
meta:{key} Term meta field
acf:{field} ACF field for term

Writable Fields

Field Key Description
post_title Post title
post_content Post content
post_excerpt Post excerpt
post_name Post slug
post_status Status (publish, draft, pending, private)
post_parent Parent post ID
menu_order Menu order
post_date Publish date
meta:{key} Any meta field
taxonomies Object with taxonomy => term IDs
featured_image Attachment ID

Code Examples

JavaScript (Fetch)

// Get posts
const getPosts = async () => {
  const response = await fetch('https://yoursite.com/wp-json/custom/v1/type/post', {
    headers: {
      'X-API-Key': 'crab_YOUR_API_KEY'
    }
  });
  return response.json();
};

// Create post
const createPost = async (title, content) => {
  const response = await fetch('https://yoursite.com/wp-json/custom/v1/type/post', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'crab_YOUR_API_KEY'
    },
    body: JSON.stringify({
      fields: {
        post_title: title,
        post_content: content,
        post_status: 'publish'
      }
    })
  });
  return response.json();
};

// Update post
const updatePost = async (id, fields) => {
  const response = await fetch(`https://yoursite.com/wp-json/custom/v1/item/${id}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'crab_YOUR_API_KEY'
    },
    body: JSON.stringify({ fields })
  });
  return response.json();
};

// Delete post
const deletePost = async (id, force = false) => {
  const response = await fetch(`https://yoursite.com/wp-json/custom/v1/item/${id}?force=${force}`, {
    method: 'DELETE',
    headers: {
      'X-API-Key': 'crab_YOUR_API_KEY'
    }
  });
  return response.json();
};

PHP (WordPress)

<?php
$api_key = 'crab_YOUR_API_KEY';
$base_url = 'https://yoursite.com/wp-json/custom/v1';

// Get posts
$response = wp_remote_get($base_url . '/type/post', array(
    'headers' => array(
        'X-API-Key' => $api_key
    )
));
$posts = json_decode(wp_remote_retrieve_body($response), true);

// Create post
$response = wp_remote_post($base_url . '/type/post', array(
    'headers' => array(
        'Content-Type' => 'application/json',
        'X-API-Key' => $api_key
    ),
    'body' => json_encode(array(
        'fields' => array(
            'post_title' => 'New Post',
            'post_content' => 'Content here',
            'post_status' => 'publish'
        )
    ))
));

// Update post
$response = wp_remote_request($base_url . '/item/123', array(
    'method' => 'PUT',
    'headers' => array(
        'Content-Type' => 'application/json',
        'X-API-Key' => $api_key
    ),
    'body' => json_encode(array(
        'fields' => array(
            'post_title' => 'Updated Title'
        )
    ))
));

// Delete post
$response = wp_remote_request($base_url . '/item/123?force=true', array(
    'method' => 'DELETE',
    'headers' => array(
        'X-API-Key' => $api_key
    )
));

Python (Requests)


import requests
import json

API_KEY = 'crab_YOUR_API_KEY'
BASE_URL = 'https://yoursite.com/wp-json/custom/v1'

headers = {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json'
}

# Get posts
response = requests.get(f'{BASE_URL}/type/post', headers=headers)
posts = response.json()

# Create post
data = {
    'fields': {
        'post_title': 'New Post from Python',
        'post_content': 'Content here',
        'post_status': 'publish'
    }
}
response = requests.post(f'{BASE_URL}/type/post', headers=headers, json=data)
result = response.json()

# Update post
data = {
    'fields': {
        'post_title': 'Updated Title'
    }
}
response = requests.put(f'{BASE_URL}/item/123', headers=headers, json=data)
result = response.json()

Read the full README on GitHub →