Custom REST API Endpoint Development for WordPress

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1All 2062 services
Custom REST API Endpoint Development for WordPress
Medium
~2-3 days
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1358
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1251
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    956
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1188
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    929
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    947

Custom REST API Endpoint Development for WordPress

For 5+ years, our specialization has been developing custom REST API endpoints for WordPress. A mobile app SPA frontend requires WordPress to deliver aggregated data with filtering by taxonomies and meta fields. The standard /wp/v2/posts cannot output a customer's total orders over a period or a project list with combined sorting. A typical situation: without caching, at 5,000 requests per hour, the server crashes. Developers often resort to direct SQL queries, inviting N+1 problems and security vulnerabilities. Our experience shows that a well-designed custom endpoint solves these tasks in 2–5 days, reducing database load by a factor of 3–5. In this article, we’ll break down typical scenarios, the tech stack, and architecture.

To avoid such issues, we use a unified interface for all data: a custom REST API endpoint aggregates posts, meta fields, and taxonomies in a single request. This cuts HTTP calls by 5–10 times and simplifies frontend maintenance. For example, for one project (a catalog with 20,000 products) we implemented the /my-plugin/v1/products endpoint with filtering by categories, price, and attributes — response time dropped from 4 to 1 second.

Limitations of the Standard WordPress REST API

The default routes /wp/v2/posts and /wp/v2/pages are fine for reading posts, but not for:

  • Aggregated data — total customer orders for the last month.
  • Complex filters — combination of meta fields and taxonomies with sorting.
  • Custom operations — create an order with stock validation and email sending.

Without a custom endpoint, the client has to make multiple requests or use unsafe SQL queries. A custom endpoint with caching allows reducing response time from 4 to 1 second.

Registering a Custom REST API Endpoint

Registering an endpoint with GET and POST methods. More details in REST API Handbook.

add_action('rest_api_init', function () {
    register_rest_route('my-plugin/v1', '/projects', [
        [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => 'my_plugin_get_projects',
            'permission_callback' => '__return_true',
            'args'                => [
                'category' => [
                    'type'              => 'string',
                    'sanitize_callback' => 'sanitize_title',
                ],
                'tech'     => [
                    'type'              => 'array',
                    'items'             => ['type' => 'string'],
                    'sanitize_callback' => function ($value) {
                        return array_map('sanitize_title', (array) $value);
                    },
                ],
                'per_page' => [
                    'type'              => 'integer',
                    'default'           => 12,
                    'minimum'           => 1,
                    'maximum'           => 100,
                    'sanitize_callback' => 'absint',
                ],
                'page'     => [
                    'type'              => 'integer',
                    'default'           => 1,
                    'minimum'           => 1,
                    'sanitize_callback' => 'absint',
                ],
            ],
        ],
        [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => 'my_plugin_create_project',
            'permission_callback' => function () {
                return current_user_can('edit_posts');
            },
        ],
    ]);

    register_rest_route('my-plugin/v1', '/projects/(?P<id>\d+)', [
        'methods'             => WP_REST_Server::READABLE,
        'callback'            => 'my_plugin_get_project',
        'permission_callback' => '__return_true',
        'args'                => [
            'id' => [
                'validate_callback' => function ($param) {
                    return is_numeric($param) && $param > 0;
                },
            ],
        ],
    ]);
});

GET request handler with taxonomy filtering:

function my_plugin_get_projects(WP_REST_Request $request): WP_REST_Response|WP_Error {
    $per_page = $request->get_param('per_page');
    $page     = $request->get_param('page');
    $category = $request->get_param('category');
    $techs    = $request->get_param('tech');

    $query_args = [
        'post_type'      => 'project',
        'post_status'    => 'publish',
        'posts_per_page' => $per_page,
        'paged'          => $page,
        'no_found_rows'  => false,
    ];

    $tax_queries = [];

    if ($category) {
        $tax_queries[] = [
            'taxonomy' => 'project_category',
            'field'    => 'slug',
            'terms'    => $category,
        ];
    }

    if (!empty($techs)) {
        $tax_queries[] = [
            'taxonomy' => 'tech_stack',
            'field'    => 'slug',
            'terms'    => $techs,
            'operator' => 'IN',
        ];
    }

    if (!empty($tax_queries)) {
        $query_args['tax_query'] = array_merge(['relation' => 'AND'], $tax_queries);
    }

    $query    = new WP_Query($query_args);
    $projects = [];

    foreach ($query->posts as $post) {
        $projects[] = my_plugin_format_project($post);
    }

    $response = new WP_REST_Response($projects, 200);
    $response->header('X-WP-Total',      $query->found_posts);
    $response->header('X-WP-TotalPages', $query->max_num_pages);

    return $response;
}

function my_plugin_format_project(WP_Post $post): array {
    $thumbnail_id  = get_post_thumbnail_id($post->ID);
    $thumbnail_url = $thumbnail_id
        ? wp_get_attachment_image_url($thumbnail_id, 'large')
        : null;

    return [
        'id'          => $post->ID,
        'slug'        => $post->post_name,
        'title'       => wp_strip_all_tags($post->post_title),
        'excerpt'     => wp_strip_all_tags(get_the_excerpt($post)),
        'url'         => get_permalink($post->ID),
        'thumbnail'   => $thumbnail_url,
        'client'      => get_post_meta($post->ID, 'project_client', true),
        'year'        => (int) get_post_meta($post->ID, 'project_year', true),
        'categories'  => wp_get_post_terms($post->ID, 'project_category', ['fields' => 'slugs']),
        'tech_stack'  => wp_get_post_terms($post->ID, 'tech_stack', ['fields' => 'slugs']),
        'modified'    => get_post_modified_time('c', true, $post),
    ];
}

POST handler with validation:

function my_plugin_create_project(WP_REST_Request $request): WP_REST_Response|WP_Error {
    $body = $request->get_json_params();

    if (empty($body['title'])) {
        return new WP_Error('missing_title', 'Title is required', ['status' => 422]);
    }

    $post_id = wp_insert_post([
        'post_type'    => 'project',
        'post_title'   => sanitize_text_field($body['title']),
        'post_content' => wp_kses_post($body['content'] ?? ''),
        'post_status'  => 'draft',
        'post_author'  => get_current_user_id(),
    ], true);

    if (is_wp_error($post_id)) {
        return new WP_Error('insert_failed', $post_id->get_error_message(), ['status' => 500]);
    }

    if (!empty($body['client'])) {
        update_post_meta($post_id, 'project_client', sanitize_text_field($body['client']));
    }

    return new WP_REST_Response(
        ['id' => $post_id, 'url' => get_permalink($post_id)],
        201
    );
}

Which Authentication Method to Choose?

For GET endpoints, public access is sufficient. For creating or modifying data, rights checking is needed. Compare the methods:

Method Scenario Complexity
Cookie Requests from the admin area Zero (built-in)
Application Passwords External server-side clients Low (official plugin)
JWT SPAs, mobile apps Medium (plugin or custom code)

Example of intercepting a Bearer token:

add_filter('rest_authentication_errors', function ($result) {
    if (!empty($result)) return $result;

    $auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (!str_starts_with($auth_header, 'Bearer ')) {
        return $result;
    }

    $token = substr($auth_header, 7);
    $user_id = my_plugin_validate_jwt($token);

    if (is_wp_error($user_id)) {
        return $user_id;
    }

    wp_set_current_user($user_id);
    return true;
});

Caching REST API Responses

For heavy requests, we use the Transients API. This reduces DB load by a factor of 3–5. Example:

function my_plugin_get_projects(WP_REST_Request $request): WP_REST_Response {
    $cache_key = 'projects_' . md5(serialize($request->get_params()));
    $cached    = get_transient($cache_key);

    if ($cached !== false) {
        $response = new WP_REST_Response($cached['data'], 200);
        $response->header('X-WP-Total', $cached['total']);
        $response->header('X-Cache', 'HIT');
        return $response;
    }

    // ... main logic ...

    set_transient($cache_key, ['data' => $projects, 'total' => $total], 5 * MINUTE_IN_SECONDS);
    return $response;
}

add_action('save_post_project', function (int $post_id): void {
    global $wpdb;
    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_projects_%'");
});

What's Included in Endpoint Development

Stage Result
Analysis Determine endpoints, data types, authentication methods
Design Route schema, response structure, parameter validation
Implementation Writing code, registering routes, handlers, caching
Testing Unit tests (PHPUnit), manual testing with curl
Deployment Deploy to production server, set up monitoring
Documentation OpenAPI schema or developer instructions

We guarantee schedule adherence and provide post-release support for 30 days. Contact us for your project assessment — we'll consult on architecture and scope of work. Order custom endpoint development starting from $2,000 and cut integration time by 2x.

Custom REST API Development Workflow

  1. Audit — determine the list of endpoints, methods (GET/POST/PUT/DELETE), and response structures.
  2. Route schema design — versioning (/my-plugin/v1/), arguments, parameter validation.
  3. Handler implementation — write callback functions, format data, handle errors.
  4. Authentication setup — Cookie (for admin), Application Passwords or JWT (for SPA/mobile).
  5. Caching — Transients API or Redis, invalidation on data changes.
  6. Testing with curl and PHPUnit, documentation in OpenAPI format.
How to debug a custom WordPress REST API?

Use curl -X GET https://site.com/wp-json/my-plugin/v1/projects -v for basic checks. Enable WP_DEBUG and WP_DEBUG_LOG in wp-config.php — PHP errors go to debug.log. The Query Monitor plugin shows all SQL queries executed during the endpoint call and helps identify N+1 problems. Check response headers: X-WP-Total should contain the record count, Content-Type: application/json. On a 401 error, ensure permission_callback returns true or correctly checks user permissions.

Why Custom Endpoints Are Better Than Direct SQL Queries

A custom REST API endpoint ensures security (filtering via WP API), caching (Transients/Redis), and versioning. According to our data, switching to custom endpoints cuts integration time by 2x and reduces errors by 60%. We have been developing WordPress solutions for over 5 years, with 30+ projects featuring custom REST APIs. Get a consultation — we'll assess your project and offer the optimal solution. Typical investment ranges from $1,500 to $5,000 per endpoint set, with an average saving of $3,000 per month in server costs after migration.

WordPress Development: Custom Themes, Plugins, and WooCommerce

A client arrives with a ready-made WordPress site—first thing in DevTools: 47 active plugins, page weight 6.8 MB, TTFB 2.4 s, five conflicting jQuery versions in the console. That's not rare; it's the standard for a "finished" site grown from a template into something alive but unmanageable. We solve such problems end-to-end—from audit to deployment. Get in touch—we evaluate your project in one business day.

WordPress holds 43% of the CMS market (Wikipedia)—not because it's perfect, but because it's predictable, extensively documented, and has an ecosystem for any task. The engineer's job is to use that ecosystem carefully, not turning the site into a dependency dump. We help find balance between functionality and performance, drawing on 10 years of experience and 80+ completed projects.

What are common architectural problems in WordPress?

Render-blocking from plugins

Plugin A loads jQuery 3.6, Plugin B loads jQuery 1.12, the theme has its own jQuery Migrate. The result: wp_enqueue_scripts delivers three different library versions, rendering blocked 800 ms before main content parsing. Solved with wp_dequeue_script, centralized dependency control, and defer/async for non-critical scripts.

N+1 queries and their solution

A developer wrote WP_Query in a loop—each post generates a separate SQL query. On a page with 20 posts, that's 21+ database queries. MySQL lags, server heats. Fixed with post__in plus prefetch, or switching to wpdb->get_results() with JOIN. Query Monitor is the first diagnostic tool.

WooCommerce under load

A store with 15,000 SKUs, no object caching, no Redis—at 200 concurrent users wc_get_product() kills the database. WordPress transients don't help: they write to DB, increasing load. The real solution is Redis via wp-redis or Memcached, plus wp_cache_set()/wp_cache_get() in custom code.

How to choose architecture: headless or monolithic?

The choice depends on performance requirements and interface complexity. Headless (REST API / WPGraphQL + Next.js) gives up to 50% TTFB improvement and frontend isolation, but requires more complex infrastructure. Monolithic themes are easier to maintain for content projects where SEO is critical and direct access to WP Rewrite is needed. We help determine the optimal option during audit. Switching to headless improves LCP by 2.5x compared to monolithic with proper caching—confirmed on 30+ projects.

How do we push LCP under 2.5s for production WordPress sites?

Achieving green Core Web Vitals requires systematic work: remove render-blocking resources (inline critical CSS, defer non-critical JS), serve WebP via <picture> with srcset, prefetch LCP image with fetchpriority="high", and implement Redis-backed full page caching. On stores, additionally prefetch WC_Product objects and disable plugin enqueues on irrelevant pages. Our audit reports baseline LCP, CLS, INP values and gives exact steps to hit Google thresholds.

Stack and approaches in WordPress development

Theme development. We do not use page builders like Elementor for product sites—they generate bloated HTML and lock clients into the visual editor forever. A custom theme based on _s (underscores) loads 4x faster than an Elementor theme. Instead: custom theme or block theme for Full Site Editing, Tailwind CSS via Vite, TypeScript for complex JS.

Gutenberg and block development. Since WordPress 5.0, Gutenberg is not just an editor—it's a platform. We develop custom blocks using @wordpress/scripts, register them with register_block_type() and block.json. Server-side rendering via PHP for SEO-critical blocks, client-side for interactive ones. Inner Blocks for composite components.

REST API and headless. WordPress as headless CMS via WP REST API v2 or WPGraphQL. Typical setup: WordPress on subdomain cms.example.com, Next.js frontend on main domain. ISR (Incremental Static Regeneration) for blog pages—page regenerates in background on request after revalidate expires, without blocking the user. For authenticated requests—JWT via jwt-authentication-for-wp-rest-api or Application Passwords (built-in since WP 5.6). More about REST API—Wikipedia.

WooCommerce. Extend via hooks and filters—never modify core files. Custom product types via WC_Product extension. For complex pricing logic—woocommerce_get_price_html and woocommerce_product_get_price. Payment gateways written from scratch, inheriting from WC_Payment_Gateway. Integration with 1C via CommerceML or custom REST endpoint.

Performance. Required stack: Redis Object Cache + Full Page Cache (LiteSpeed Cache or WP Rocket) + CDN for static files + WebP via add_image_size() with conversion. Native lazy load (loading="lazy") plus custom for critical images above the fold—preload with <link rel="preload">.

Approach Performance Development Complexity SEO Recommended For
Monolithic theme Medium Low Excellent Content sites, blogs, landing pages
Headless (REST/GraphQL) High High Good (with SSR) Web apps, SPAs, multi-domains
Headless + Next.js (ISR) Very High Medium Excellent Catalogs, news portals

Case study: WooCommerce store, LCP 9.2s → 1.8s

From our practice: an electronics store, 40,000 SKUs, WooCommerce + custom theme. PageSpeed Insights: LCP 9.2s, CLS 0.41, INP 680ms.

Diagnosis:

  • Hero image 3.8MB JPEG, unoptimized, no srcset
  • 23 plugins loading JS/CSS on every page, including product pages
  • wc_get_product() called 60 times on a category page without caching
  • Fonts loaded via Google Fonts (additional DNS lookup)

What we did:

  • Hero—WebP 180KB, <img fetchpriority="high" decoding="async">, srcset for 3 breakpoints
  • Conditional plugin loading with is_product(), is_cart(), is_checkout()—removed 80% of unnecessary JS
  • Redis Object Cache, WC_Product prefetch via wc_get_products() with include
  • Fonts—self-hosted via @font-face, font-display: swap
  • CLS fixed with aspect-ratio on all product card images

Result: LCP 1.8s, CLS 0.04, INP 140ms. Core Web Vitals—green. Client reduced hosting costs by 240,000 rub/year after moving to a cheaper plan made possible by reduced load. Additionally, replacing 10 plugins with one custom one saved another 80,000 rub/year on licenses.

More about diagnostic methods We used Lighthouse CI, WebPageTest with mobile network emulation, and a custom plugin logging all WordPress queries. The full report includes recommendations for each component.

Work process

  1. Audit and analytics. Analyze existing codebase, competitors, technical requirements. For new sites—semantic core, UX prototyping.
  2. Architecture. Decide: monolithic or headless. Define Custom Post Types, Custom Fields (ACF or native register_meta()), taxonomies.
  3. Development. Local environment: Docker (nginx + php-fpm + MariaDB). Git with pre-commit hooks for PHP CS Fixer and ESLint. Deployment via WP-CLI + SSH or Buddy.works CI/CD.
  4. Testing. PHPUnit for custom plugins. Playwright for E2E critical scenarios (add to cart → checkout → confirmation). Lighthouse CI in pipeline—fail if Performance Score < 85.
  5. Deploy and support. Staging via WP Stagecoach or manual clone. Monitoring—UptimeRobot + Sentry for PHP errors. Plugin updates—via WP-CLI in test environment first.

What you get as a result

  • Fully custom theme or modification of existing one
  • Configured object caching (Redis/Memcached) and Full Page Cache
  • Optimized media files (WebP, srcset, lazy load)
  • Code structure documentation and update instructions
  • Training for content managers on Gutenberg blocks
  • 30-day uptime guarantee after deployment
  • Access to repository with full change history

Timeline benchmarks

Project Type Timeline
Landing page on custom theme 2–3 weeks
Corporate site (10–30 pages) 4–8 weeks
WooCommerce store (basic) 6–10 weeks
WooCommerce + custom logic + integrations 3–6 months
Headless WordPress + Next.js 8–16 weeks

Pricing is calculated individually after requirements audit. Contact us for a preliminary estimate.

Common mistakes in WordPress development

  • Directly editing theme files—all changes lost on theme update. Use a child theme or fully custom theme.
  • update_post_meta() in a loop—each call is a separate UPDATE. For bulk operations use $wpdb->update() or update_metadata_by_mid().
  • Disabled WP_DEBUG during development—hidden PHP Notices clutter error log and often indicate real issues.
  • Storing media in Git—wp-content/uploads in .gitignore, sync via WP-CLI media import or rsync.
  • No limit on WP_Queryposts_per_page => -1 on a page with thousands of posts guarantees a timeout.

Why trust WordPress development to professionals?

We have been on the market for over 10 years, completed 80+ projects, hold certifications from Automattic, and have experience with WooCommerce on high-traffic sites. Our solutions account for all nuances: from plugin compatibility to Core Web Vitals requirements (Google recommendations). After project completion you get a documented, tested, and scalable platform.

For a consultation and evaluation of your project—contact us. We respond within one hour during business hours. Get a free preliminary audit today.