Mastering the WP Engine API: A Comprehensive Guide for Developers

Kellen Mace Avatar

·

In today’s fast-paced digital landscape, automation is key to efficient workflow management. For developers and agencies working with WordPress sites hosted on WP Engine, the WP Engine API offers powerful capabilities to programmatically manage your hosting infrastructure. Whether you’re managing a single site or hundreds, the API enables you to automate repetitive tasks, integrate with your existing tools, and build custom workflows tailored to your needs.

This guide will cover everything you need to know about the WP Engine API, from basic concepts to advanced implementation strategies. It includes practical code examples using Node.js/JavaScript. An example WP Engine Site Management CLI Tool app is also provided that demonstrates how to use the API in practice.

A video covering this same topic is also available here:

Prerequisites

To get the most out of this guide, you should have:

  • Basic familiarity with JavaScript and Node.js
  • Experience working with REST APIs (making HTTP requests, handling JSON responses)
  • Node.js installed

What is the WP Engine API?

The WP Engine API is a RESTful API that allows customers to interact with their WP Engine account programmatically. Rather than manually performing tasks in the WP Engine User Portal, you can use the API to automate those tasks, saving time and reducing the potential for human error.

The API follows RESTful principles and uses standard HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources. It returns data in JSON format, making it easy to integrate with any programming language or framework.

Common Use Cases

The WP Engine API is particularly useful for:

  • Agencies managing multiple client sites: Automate site creation, user management, and domain configuration
  • DevOps teams: Integrate WP Engine operations into CI/CD pipelines
  • Custom dashboards: Build custom interfaces for your team or clients
  • Scheduled maintenance: Automate routine tasks like creating backups or purging caches
  • Bulk operations: Perform actions across multiple sites simultaneously

What You Can Do with the API

The WP Engine API allows you to perform a wide range of operations, including:

  • List your WP Engine accounts
  • Manage account users (add, update, delete)
  • List and manage sites
  • Manage installs/environments (add, delete)
  • Configure domains (add, delete, set primary)
  • Create backups
  • Purge caches
  • Manage SSH keys

It’s important to note that some operations are not currently available through the API, such as copying or transferring environments, restoring backups, managing SSL, and several other specialized tasks. For a complete list of supported and unsupported operations, refer to the WP Engine API Support Center page and the official documentation.

Getting Started with the WP Engine API

Authentication

The WP Engine API uses Basic Authentication. To authenticate your requests, you’ll need to generate API credentials from the WP Engine User Portal.

  1. Log in to the WP Engine User Portal
  2. Navigate to API Access in the left sidebar
  3. Click “Generate Credentials” if you don’t have any
  4. Copy your API username and password

These steps are also listed on the WP Engine API Support Center page.

Your credentials will be used to authenticate all your API requests. Keep them secure, as they provide access to your WP Engine resources.

Making Your First API Request

Let’s start with a simple example: retrieving information about the authenticated user. This is a great way to test your API credentials and ensure everything is set up correctly.

// user-info.js

// Replace with your actual credentials
const API_USER_ID = "your-api-user-id";
const API_PASSWORD = "your-api-password";

// Create the authorization header
const auth = Buffer.from(`${API_USER_ID}:${API_PASSWORD}`).toString("base64");

async function getUserInfo() {
  try {
    const response = await fetch("https://api.wpengineapi.com/v1/user", {
      headers: { Authorization: `Basic ${auth}` },
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("User Information:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error fetching user information:", error);
    throw error;
  }
}

// Execute the function
getUserInfo();
Code language: JavaScript (javascript)

To run this code on your local machine, you can:

  1. Create a file called user-info.js
  2. Paste this code into it
  3. Insert your API credentials
  4. Run it with node user-info.js.

This script makes a GET request to the /user endpoint, which returns information about the authenticated user. If successful, it will display your user details in the console, like this:

{
  "id": "d84kd9f4-2c8w-op38-826x-16zje9c84ngp",
  "email": "[email protected]",
  "first_name": "Walter",
  "last_name": "Engine",
  "phone_number": null
}
Code language: JSON / JSON with Comments (json)

NOTE: Your API credentials are sensitive, so be sure never to post them publicly or commit them to version control.

Core API Functionality

Now that we’ve covered the basics, let’s explore the core functionality of the WP Engine API with practical examples.

Auth Helper Function

All of the examples below use a utility function called createAuthHeader to get the API credentials from environment variables and generate the Basic Authentication header for WP Engine API requests:

import dotenv from "dotenv";

// Load environment variables from .env file
dotenv.config();

/**
 * Create a Basic Authentication header for WP Engine API requests
 * @returns The Base64 encoded authentication string
 */
export function createAuthHeader() {
  const API_USER_ID = process.env.WP_ENGINE_API_USER_ID || "";
  const API_PASSWORD = process.env.WP_ENGINE_API_PASSWORD || "";

  if (!API_USER_ID || !API_PASSWORD) {
    console.error(
      "Error: WP Engine API credentials not found in environment variables."
    );
    console.error(
      "Please create a .env file with WP_ENGINE_API_USER_ID and WP_ENGINE_API_PASSWORD."
    );
    process.exit(1);
  }

  // Create the authorization header
  const auth = Buffer.from(`${API_USER_ID}:${API_PASSWORD}`).toString("base64");
  return `Basic ${auth}`;
}
Code language: JavaScript (javascript)

You can set up a similar helper function in your project to generate the auth header for all API requests, if you like.

Account Management

Listing Accounts

To retrieve a list of WP Engine accounts that the authenticated user has access to:

import { createAuthHeader } from "./utils.js";

async function listAccounts() {
  try {
    const response = await fetch("https://api.wpengineapi.com/v1/accounts", {
      headers: { Authorization: createAuthHeader() },
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Accounts:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error fetching accounts:", error);
    throw error;
  }
}

listAccounts();
Code language: JavaScript (javascript)

Managing Account Users

You can add, update, or remove users from your WP Engine account:

import { createAuthHeader } from "./utils.js";

async function addAccountUser(accountId, email, role) {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/accounts/${accountId}/users`,
      {
        method: "POST",
        headers: {
          Authorization: createAuthHeader(),
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          email,
          role, // 'admin', 'developer', 'sftp', 'billing', 'support', 'partial'
        }),
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("User added successfully:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error adding user:", error);
    throw error;
  }
}

// Example usage
// addAccountUser('your-account-id', '[email protected]', 'developer');
Code language: JavaScript (javascript)

Site Management

Listing Sites

To retrieve a list of sites associated with your account:

import { createAuthHeader } from "./utils.js";

async function listSites() {
  try {
    const response = await fetch("https://api.wpengineapi.com/v1/sites", {
      headers: { Authorization: createAuthHeader() },
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Sites:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error fetching sites:", error);
    throw error;
  }
}

listSites();
Code language: JavaScript (javascript)

Creating a New Site

To create a new site on WP Engine:

import { createAuthHeader } from "./utils.js";

async function createSite(name) {
  try {
    const response = await fetch("https://api.wpengineapi.com/v1/sites", {
      method: "POST",
      headers: {
        Authorization: createAuthHeader(),
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ name }),
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Site created successfully:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error creating site:", error);
    throw error;
  }
}

// Example usage
// createSite('my-new-site');
Code language: JavaScript (javascript)

Install (Environment) Management

Listing Installs

To retrieve a list of installs (environments) associated with your account:

import { createAuthHeader } from "./utils.js";

async function listInstalls() {
  try {
    const response = await fetch("https://api.wpengineapi.com/v1/installs", {
      headers: { Authorization: createAuthHeader() },
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Installs:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error fetching installs:", error);
    throw error;
  }
}

listInstalls();

Code language: JavaScript (javascript)

Creating a New Install

To create a new install (environment) on WP Engine:

import { createAuthHeader } from "./utils.js";

async function createInstall(siteId, name, environment) {
  try {
    const response = await fetch("https://api.wpengineapi.com/v1/installs", {
      method: "POST",
      headers: {
        Authorization: createAuthHeader(),
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        site_id: siteId,
        name,
        environment, // 'production', 'staging', 'development'
      }),
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Install created successfully:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error creating install:", error);
    throw error;
  }
}

// Example usage
// createInstall('your-site-id', 'my-new-install', 'staging');

Code language: JavaScript (javascript)

Domain Management

Listing Domains

To retrieve a list of domains associated with an install:

import { createAuthHeader } from "./utils.js";

async function listDomains(installId) {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/installs/${installId}/domains`,
      {
        headers: { Authorization: createAuthHeader() },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Domains:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error fetching domains:", error);
    throw error;
  }
}

// Example usage
// listDomains('your-install-id');

Code language: JavaScript (javascript)

Adding a Domain

To add a new domain to an install:

import { createAuthHeader } from "./utils.js";

async function addDomain(installId, name, primary = false) {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/installs/${installId}/domains`,
      {
        method: "POST",
        headers: {
          Authorization: createAuthHeader(),
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          name,
          primary,
        }),
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Domain added successfully:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error adding domain:", error);
    throw error;
  }
}

// Example usage
// addDomain('your-install-id', 'example.com', true);

Code language: JavaScript (javascript)

Backup Management

Creating a Backup

To create a backup of an install:

import { createAuthHeader } from "./utils.js";

async function createBackup(installId, description) {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/installs/${installId}/backups`,
      {
        method: "POST",
        headers: {
          Authorization: createAuthHeader(),
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ description }),
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Backup created successfully:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error creating backup:", error);
    throw error;
  }
}

// Example usage
// createBackup('your-install-id', 'Pre-deployment backup');

Code language: JavaScript (javascript)

Listing Backups

To retrieve a list of backups for an install:

import { createAuthHeader } from "./utils.js";

async function listBackups(installId) {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/installs/${installId}/backups`,
      {
        headers: { Authorization: createAuthHeader() },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log("Backups:");
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error("Error fetching backups:", error);
    throw error;
  }
}

// Example usage
// listBackups('your-install-id');

Code language: JavaScript (javascript)

Cache Management

Purging Cache

To purge the cache for an install:

import { createAuthHeader } from "./utils.js";

async function purgeCache(installId, type = "all") {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/installs/${installId}/caches/${type}`,
      {
        method: "POST",
        headers: {
          Authorization: createAuthHeader(),
          "Content-Type": "application/json",
        },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log(`${type} cache purged successfully:`);
    console.log(JSON.stringify(data, null, 2));
    return data;
  } catch (error) {
    console.error(`Error purging ${type} cache:`, error);
    throw error;
  }
}

// Example usage
// purgeCache('your-install-id', 'all');

Code language: JavaScript (javascript)

A Complete Example: WP Engine Site Management CLI Tool

To see a practical implementation of the concepts covered in this guide, check out the WP Engine Site Management CLI Tool. This open-source tool demonstrates how to interact with the WP Engine API from the command line, allowing developers to efficiently manage their WP Engine sites and installs:

Key Features

With this CLI tool, you can:

  • Browse accounts you have access to
  • View sites within each account
  • View installs (environments) within each site
  • Create and delete sites
  • Create and delete installs (environments)

For detailed usage instructions and setup steps, please follow the guidance provided in the project’s README.

Reading through the source code for this CLI tool will give you a good understanding of how multiple API endpoints can be used together to perform complex operations.

Advanced Topics

Pagination

The WP Engine API uses offset-based pagination for list operations. You can control the number of results per page using the limit parameter (maximum 100) and specify the starting point with the offset parameter.

import { createAuthHeader } from "./utils.js";

async function getPaginatedList(endpoint, limit = 100, offset = 0) {
  try {
    const response = await fetch(
      `https://api.wpengineapi.com/v1/${endpoint}?limit=${limit}&offset=${offset}`,
      {
        headers: { Authorization: createAuthHeader() },
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log(`${endpoint} (limit: ${limit}, offset: ${offset}):`);
    console.log(`Total items: ${data.count}`);
    console.log(`Items in this page: ${data.results.length}`);

    // Check if there are more pages
    if (data.next) {
      console.log(`Next page available at: ${data.next}`);
    }

    return data;
  } catch (error) {
    console.error(`Error fetching paginated list for ${endpoint}:`, error);
    throw error;
  }
}

// Example usage
// getPaginatedList('installs', 10, 0);

Code language: JavaScript (javascript)

Error Handling

The WP Engine API uses standard HTTP response codes to indicate the success or failure of requests. Here’s how to implement robust error handling:

import { createAuthHeader } from "./utils.js";

async function makeApiRequest(method, endpoint, data = null) {
  try {
    const options = {
      method,
      headers: {
        Authorization: createAuthHeader(),
        "Content-Type": "application/json",
      },
    };

    if (method !== "GET" && data) {
      options.body = JSON.stringify(data);
    }

    const response = await fetch(
      `https://api.wpengineapi.com/v1/${endpoint}`,
      options
    );

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({}));
      const status = response.status;

      switch (status) {
        case 400:
          console.error(
            "Bad Request: The request was invalid or cannot be served.",
            errorData
          );
          break;
        case 401:
          console.error(
            "Unauthorized: Authentication failed or user does not have permissions.",
            errorData
          );
          break;
        case 404:
          console.error(
            "Not Found: The requested resource does not exist.",
            errorData
          );
          break;
        case 429:
          console.error("Too Many Requests: Rate limit exceeded.", errorData);
          // Implement retry logic with exponential backoff
          break;
        case 503:
          console.error(
            "Service Unavailable: The server is currently unavailable.",
            errorData
          );
          // Implement retry logic
          break;
        default:
          console.error(`Error ${status}:`, errorData);
      }

      throw new Error(`HTTP error! status: ${status}`);
    }

    return await response.json();
  } catch (error) {
    if (error instanceof TypeError) {
      // Network error or other fetch-related error
      console.error("Network error:", error.message);
    } else {
      // Handle other errors
      console.error("Unexpected error:", error);
    }

    throw error;
  }
}

// Example usage
// makeApiRequest('GET', 'installs');

Code language: JavaScript (javascript)

Rate Limiting

The WP Engine API implements rate limiting to prevent abuse. If you exceed the rate limits, you’ll receive a 429 Too Many Requests response. To handle this gracefully, implement a retry mechanism with exponential backoff:

import { createAuthHeader } from "./utils.js";

async function makeApiRequestWithRetry(
  method,
  endpoint,
  data = null,
  maxRetries = 3,
  initialDelay = 1000
) {
  let retries = 0;
  let delay = initialDelay;

  while (true) {
    try {
      const options = {
        method,
        headers: {
          Authorization: createAuthHeader(),
          "Content-Type": "application/json",
        },
      };

      if (method !== "GET" && data) {
        options.body = JSON.stringify(data);
      }

      const response = await fetch(
        `https://api.wpengineapi.com/v1/${endpoint}`,
        options
      );

      if (response.status === 429 && retries < maxRetries) {
        // Rate limit exceeded, retry after delay
        retries++;
        console.log(
          `Rate limit exceeded. Retrying in ${delay}ms... (${retries}/${maxRetries})`
        );
        await new Promise((resolve) => setTimeout(resolve, delay));
        delay *= 2; // Exponential backoff
        continue;
      }

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      return await response.json();
    } catch (error) {
      if (retries >= maxRetries) {
        console.error("Max retries reached. Giving up.");
        throw error;
      }

      if (!(error instanceof Error && error.message.includes("429"))) {
        throw error; // Only retry on rate limit errors
      }

      retries++;
      console.log(
        `Error: ${error.message}. Retrying in ${delay}ms... (${retries}/${maxRetries})`
      );
      await new Promise((resolve) => setTimeout(resolve, delay));
      delay *= 2; // Exponential backoff
    }
  }
}

// Example usage
// makeApiRequestWithRetry('GET', 'installs');

Code language: JavaScript (javascript)

Best Practices

Security Considerations

  1. Protect your API credentials: Store your API credentials securely and never expose them in client-side code.
  2. Use environment variables: Store sensitive information like API credentials in environment variables rather than hardcoding them in your application.
  3. Implement proper error handling: Handle errors gracefully to prevent exposing sensitive information in error messages.
  4. Validate input: Always validate and sanitize user input before using it in API requests.

Performance Optimization

  1. Use pagination: When retrieving large datasets, use pagination to limit the amount of data transferred in a single request.
  2. Implement caching: Cache API responses when appropriate to reduce the number of requests made to the API.
  3. Batch operations: When possible, batch multiple operations into a single request to reduce overhead.
  4. Handle rate limits: Implement retry mechanisms with exponential backoff to handle rate limiting gracefully.

Monitoring and Logging

  1. Log API requests and responses: Keep logs of API interactions for debugging and auditing purposes.
  2. Monitor API usage: Track your API usage to stay within rate limits and identify potential issues.
  3. Set up alerts: Configure alerts for API errors or unusual patterns to catch issues early.

Conclusion

The WP Engine API provides a powerful way to automate and streamline your WordPress hosting management. By leveraging the API, you can build custom tools and workflows that save time, reduce errors, and improve efficiency.

This guide has covered the fundamentals of working with the WP Engine API, from authentication and basic operations to advanced topics like pagination, error handling, and rate limiting. The accompanying code examples demonstrate how to implement these concepts in practice using Node.js/JavaScript.

As you continue to explore the WP Engine API, remember to refer to the official documentation for the most up-to-date information and best practices.

Happy coding!


Resources