Creating Custom API Endpoints in WordPress with PHP and JavaScript”
June 30, 2025In today’s modern development workflows, connecting third-party services like Klaviyo, Mailchimp, or Stripe requires more than just dropping in some HTML. You usually need a secure server-side connection—typically built in PHP or another backend language.
In this article, I’ll show you two approaches to creating a custom API endpoint in WordPress:
Using the legacy admin-ajax.php method
Using the modern WordPress REST API
Both are valid—depending on your use case—and I’ll walk you through connecting to the Klaviyo API as an example.
Why Not Use Klaviyo’s Out-of-the-Box Embed?
Klaviyo gives you a simple embed solution for newsletter signup forms—just paste in their script and go. But that approach:
Injects a large chunk of unused HTML, CSS, and JavaScript
Limits customization and branding
Can slow down your site performance
If you want full control over the design and speed of your site, building a direct integration using your own code is the better way.
Method 1: admin-ajax.php (The Classic Way)
WordPress offers a built-in way to trigger PHP functions via AJAX using the admin-ajax.php system. It works great for quick server-side processing.
Step 1: Add This to Your functions.php
function submit_klaviyo_newsletter_signup() { $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; if (empty($email)) { wp_send_json_error(['message' => 'Email is required.']); } $api_key = 'YOUR_KLAVIYO_PRIVATE_API_KEY'; $list_id = 'YOUR_LIST_ID'; $url = 'https://a.klaviyo.com/api/v2/list/' . $list_id . '/subscribe'; $body = json_encode([ 'api_key' => $api_key, 'profiles' => [ ['email' => $email] ] ]); $response = wp_remote_post($url, [ 'headers' => ['Content-Type' => 'application/json'], 'body' => $body, ]); if (is_wp_error($response)) { wp_send_json_error(['message' => 'API request failed.']); } wp_send_json_success(['message' => 'Subscription successful.']); } add_action('wp_ajax_submitKlaviyoNewsletterSignup', 'submit_klaviyo_newsletter_signup'); add_action('wp_ajax_nopriv_submitKlaviyoNewsletterSignup', 'submit_klaviyo_newsletter_signup');
Step 2: Call the Endpoint with JavaScript
function subscribeToNewsletter() { const email = document.querySelector('#email').value; const formData = new FormData(); formData.append('action', 'submitKlaviyoNewsletterSignup'); formData.append('email', email); fetch('/wp-admin/admin-ajax.php', { method: 'POST', body: formData }) .then(res => res.json()) .then(data => { if (data.success) { alert(data.data.message); } else { alert('Error: ' + data.data.message); } }); }
Method 2: WordPress REST API (Recommended)
If you’re building a modern front-end or just want better RESTful design patterns, the WordPress REST API is the way to go.
Step 1: Register Your Custom Endpoint
add_action('rest_api_init', function () { register_rest_route('custom/v1', '/klaviyo-subscribe', [ 'methods' => 'POST', 'callback' => 'handle_klaviyo_rest_signup', 'permission_callback' => '__return_true', // Add proper auth in production ]); }); function handle_klaviyo_rest_signup($request) { $email = sanitize_email($request->get_param('email')); if (empty($email)) { return new WP_REST_Response(['message' => 'Email is required.'], 400); } $api_key = 'YOUR_KLAVIYO_PRIVATE_API_KEY'; $list_id = 'YOUR_LIST_ID'; $url = 'https://a.klaviyo.com/api/v2/list/' . $list_id . '/subscribe'; $body = json_encode([ 'api_key' => $api_key, 'profiles' => [ ['email' => $email] ] ]); $response = wp_remote_post($url, [ 'headers' => ['Content-Type' => 'application/json'], 'body' => $body, ]); if (is_wp_error($response)) { return new WP_REST_Response(['message' => 'Request failed.'], 500); } return new WP_REST_Response(['message' => 'Subscribed successfully!'], 200); }
Step 2: Use JavaScript to Post to the Endpoint
function subscribeViaRest() { const email = document.querySelector('#email').value; fetch('/wp-json/custom/v1/klaviyo-subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }) .then(res => res.json()) .then(data => { alert(data.message); }); }
Bonus: Automate Testing with GitHub Actions
If you’re maintaining a plugin or want to ensure good code quality over time, here’s a quick GitHub Action to run PHP linting and WordPress coding standards checks.
name: PHP Code Quality on: [push, pull_request] jobs: linting: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up PHP uses: shivammathur/setup-php@v2 with: php-version: '8.1' - name: Run PHP Lint run: find . -type f -name "*.php" -exec php -l {} \; - name: Run WordPress Coding Standards run: vendor/bin/phpcs --standard=WordPress .
Final Thoughts
Connecting to third-party APIs in WordPress doesn’t have to involve bloated scripts or slow-loading embeds. With just a few lines of PHP and JavaScript, you can create clean, fast, and secure endpoints to handle just about anything—from newsletter signups to data syncing and beyond.
If you need help wiring this into a production project or want to expand this with authentication, error logging, or front-end validation, drop me a line—I’d love to help.
