Skip to main content

WordPress HTTP API

Introduction

When developing WordPress plugins, you'll often need to interact with external services, fetch remote data, or communicate with third-party APIs. The WordPress HTTP API provides a standardized and secure way to make HTTP requests from your plugins without having to write low-level code or manage complex dependencies.

Instead of using PHP's native functions like file_get_contents() or requiring external libraries, WordPress offers a robust set of functions that handle common HTTP operations while managing errors, timeouts, and other complexities automatically.

In this tutorial, we'll explore how to use the WordPress HTTP API to make various types of requests, handle responses, and implement typical use cases in plugin development.

Why Use the WordPress HTTP API?

Before diving into the code, it's important to understand the benefits of using WordPress's built-in HTTP functions:

  • Compatibility: Works across different hosting environments
  • Security: Handles sanitization and validation automatically
  • Flexibility: Supports various methods (GET, POST, PUT, etc.)
  • Error handling: Robust error detection and reporting
  • Standardization: Consistent interface for all HTTP operations

Basic HTTP Requests

Making a Simple GET Request

The most common HTTP request is GET, used to retrieve data from an external URL.

php
function my_plugin_get_remote_data() {
$api_url = 'https://api.example.com/data';

// Basic GET request
$response = wp_remote_get($api_url);

// Check if the request was successful
if (is_wp_error($response)) {
return 'Error: ' . $response->get_error_message();
}

// Get response code
$response_code = wp_remote_retrieve_response_code($response);

if ($response_code === 200) {
// Get the body of the response
$body = wp_remote_retrieve_body($response);
return $body;
} else {
return 'Error: Received response code ' . $response_code;
}
}

Understanding the Response

The wp_remote_get() function returns either a WP_Error object (if the request failed) or an array containing:

  • headers: Response headers
  • body: The response content
  • response: HTTP status code and message
  • cookies: Any cookies set in the response
  • filename: Only if 'stream' => true was set

Here's how to access each part of the response:

php
function my_plugin_parse_response($response) {
if (is_wp_error($response)) {
return 'Error: ' . $response->get_error_message();
}

// Get response code (e.g., 200, 404, 500)
$code = wp_remote_retrieve_response_code($response);

// Get response message (e.g., "OK", "Not Found")
$message = wp_remote_retrieve_response_message($response);

// Get headers as an array
$headers = wp_remote_retrieve_headers($response);

// Get individual header
$content_type = wp_remote_retrieve_header($response, 'content-type');

// Get body content
$body = wp_remote_retrieve_body($response);

return [
'code' => $code,
'message' => $message,
'content_type' => $content_type,
'body' => $body
];
}

Advanced HTTP Requests

POST Requests

When you need to send data to a remote API, you'll typically use POST requests:

php
function my_plugin_post_data() {
$api_url = 'https://api.example.com/submit';

$body = [
'username' => 'john_doe',
'email' => '[email protected]',
'message' => 'Hello from my WordPress plugin!'
];

$args = [
'body' => $body,
'timeout' => 30, // 30-second timeout
];

$response = wp_remote_post($api_url, $args);

if (is_wp_error($response)) {
return 'Error: ' . $response->get_error_message();
}

$response_code = wp_remote_retrieve_response_code($response);

if ($response_code === 201 || $response_code === 200) {
return 'Success! Data submitted.';
} else {
return 'Error: Received response code ' . $response_code;
}
}

Other HTTP Methods

For other HTTP methods like PUT, DELETE, or PATCH, you can use the more generic wp_remote_request() function:

php
function my_plugin_update_resource($resource_id, $data) {
$api_url = 'https://api.example.com/resources/' . $resource_id;

$args = [
'method' => 'PUT',
'body' => $data,
'headers' => [
'Content-Type' => 'application/json',
],
];

$response = wp_remote_request($api_url, $args);

// Process response as usual
// ...
}

Working with JSON APIs

Most modern APIs use JSON for data exchange. Here's how to work with JSON APIs:

php
function my_plugin_fetch_json_api() {
$api_url = 'https://api.example.com/products';

$args = [
'headers' => [
'Accept' => 'application/json',
],
];

$response = wp_remote_get($api_url, $args);

if (is_wp_error($response)) {
return 'Error: ' . $response->get_error_message();
}

$body = wp_remote_retrieve_body($response);

// Convert JSON to PHP array/object
$data = json_decode($body, true); // true to get associative array

if (json_last_error() !== JSON_ERROR_NONE) {
return 'Error parsing JSON: ' . json_last_error_msg();
}

// Now $data contains the PHP representation of the JSON
return $data;
}

Authentication Methods

Many APIs require authentication. Here are common ways to authenticate:

Basic Authentication

php
function my_plugin_basic_auth_request() {
$api_url = 'https://api.example.com/protected-resource';
$username = 'api_user';
$password = 'api_password';

$args = [
'headers' => [
'Authorization' => 'Basic ' . base64_encode($username . ':' . $password),
],
];

$response = wp_remote_get($api_url, $args);

// Process response as usual
// ...
}

API Key Authentication

php
function my_plugin_api_key_request() {
$api_url = 'https://api.example.com/data';
$api_key = 'your_api_key_here';

// API key in header
$args = [
'headers' => [
'X-API-Key' => $api_key,
],
];

// Or API key in URL (less secure)
// $api_url = add_query_arg('api_key', $api_key, $api_url);

$response = wp_remote_get($api_url, $args);

// Process response as usual
// ...
}

OAuth Authentication

OAuth is more complex. Here's a simplified example:

php
function my_plugin_oauth_request() {
$api_url = 'https://api.example.com/data';
$access_token = get_option('my_plugin_oauth_token');

$args = [
'headers' => [
'Authorization' => 'Bearer ' . $access_token,
],
];

$response = wp_remote_get($api_url, $args);

// Check for unauthorized error (token expired)
if (wp_remote_retrieve_response_code($response) === 401) {
$access_token = my_plugin_refresh_oauth_token();

// Try again with new token
$args['headers']['Authorization'] = 'Bearer ' . $access_token;
$response = wp_remote_get($api_url, $args);
}

// Process response as usual
// ...
}

Additional Request Options

The WordPress HTTP API supports many options to customize requests:

php
function my_plugin_advanced_request() {
$api_url = 'https://api.example.com/large-file';

$args = [
'timeout' => 60, // 60 second timeout
'redirection' => 5, // Maximum 5 redirects
'httpversion' => '1.1', // Use HTTP/1.1
'user-agent' => 'My Plugin/1.0; ' . get_bloginfo('url'), // Custom user agent
'blocking' => true, // Wait for response
'headers' => [], // Custom headers
'cookies' => [], // Custom cookies
'body' => null, // Request body
'compress' => false, // Don't compress
'decompress' => true, // Decompress if compressed
'sslverify' => true, // Verify SSL certificate
'stream' => false, // Don't stream to file
'filename' => null // Filename if streaming
];

$response = wp_remote_get($api_url, $args);

// Process response as usual
// ...
}

Real-World Examples

Example 1: Fetching Weather Data

Let's create a function that fetches weather data from a public API:

php
function my_weather_plugin_get_forecast($city) {
$api_key = get_option('my_weather_plugin_api_key');
$api_url = 'https://api.weatherapi.com/v1/forecast.json';

$args = [
'q' => $city,
'key' => $api_key,
'days' => 3
];

$request_url = add_query_arg($args, $api_url);
$response = wp_remote_get($request_url);

if (is_wp_error($response)) {
return [
'success' => false,
'message' => $response->get_error_message()
];
}

$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);

if (!$data || isset($data['error'])) {
return [
'success' => false,
'message' => isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error'
];
}

// Process the weather data
$forecast = [];
foreach ($data['forecast']['forecastday'] as $day) {
$forecast[] = [
'date' => $day['date'],
'max_temp' => $day['day']['maxtemp_c'],
'min_temp' => $day['day']['mintemp_c'],
'condition' => $day['day']['condition']['text']
];
}

return [
'success' => true,
'city' => $data['location']['name'],
'country' => $data['location']['country'],
'forecast' => $forecast
];
}

Example 2: Posting to a CRM System

This example shows how to submit a lead to a CRM system:

php
function my_crm_plugin_create_lead($lead_data) {
$api_url = 'https://api.mycrm.com/v1/leads';
$api_key = get_option('my_crm_plugin_api_key');

// Prepare data in format expected by the CRM
$body = [
'lead' => [
'first_name' => sanitize_text_field($lead_data['first_name']),
'last_name' => sanitize_text_field($lead_data['last_name']),
'email' => sanitize_email($lead_data['email']),
'phone' => sanitize_text_field($lead_data['phone']),
'source' => 'WordPress Website'
]
];

$args = [
'body' => json_encode($body),
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $api_key
],
'timeout' => 45,
'data_format' => 'body'
];

$response = wp_remote_post($api_url, $args);

if (is_wp_error($response)) {
error_log('CRM Lead Creation Error: ' . $response->get_error_message());
return false;
}

$response_code = wp_remote_retrieve_response_code($response);
$response_body = json_decode(wp_remote_retrieve_body($response), true);

if ($response_code === 201 || $response_code === 200) {
// Save the CRM lead ID to WordPress for future reference
if (isset($response_body['lead']['id'])) {
return $response_body['lead']['id'];
}
return true;
} else {
error_log('CRM Error: ' . json_encode($response_body));
return false;
}
}

Error Handling and Best Practices

Proper Error Handling

Always check for errors using is_wp_error():

php
function my_plugin_safe_request($url) {
$response = wp_remote_get($url);

if (is_wp_error($response)) {
// Log the error
error_log('API Request Error: ' . $response->get_error_message());

// Maybe notify admin
if (current_user_can('manage_options')) {
add_action('admin_notices', function() use ($response) {
echo '<div class="error"><p>API Error: ' .
esc_html($response->get_error_message()) .
'</p></div>';
});
}

return false;
}

$response_code = wp_remote_retrieve_response_code($response);

if ($response_code < 200 || $response_code >= 300) {
// Log the error
error_log('API HTTP Error: ' . $response_code);
return false;
}

return wp_remote_retrieve_body($response);
}

Caching API Responses

For better performance and to avoid hitting rate limits:

php
function my_plugin_cached_api_request($endpoint) {
// Generate a unique cache key
$cache_key = 'my_plugin_api_' . md5($endpoint);

// Try to get cached response
$cached_response = get_transient($cache_key);

if ($cached_response !== false) {
return $cached_response;
}

// Make the actual request
$api_url = 'https://api.example.com/' . $endpoint;
$response = wp_remote_get($api_url);

if (is_wp_error($response)) {
return false;
}

$data = wp_remote_retrieve_body($response);

// Cache the result (for 1 hour)
set_transient($cache_key, $data, HOUR_IN_SECONDS);

return $data;
}

Rate Limiting

To prevent hitting API rate limits:

php
function my_plugin_rate_limited_request($endpoint) {
$last_request_time = get_option('my_plugin_last_api_request', 0);
$current_time = time();

// Ensure we wait at least 1 second between requests
if ($current_time - $last_request_time < 1) {
// Wait a bit
sleep(1);
}

// Make the request
$response = wp_remote_get('https://api.example.com/' . $endpoint);

// Update the last request time
update_option('my_plugin_last_api_request', time());

return $response;
}

Security Considerations

When working with the WordPress HTTP API, keep these security practices in mind:

  1. Never expose API keys in client-side code - Always make requests server-side

  2. Validate and sanitize all data - Both data sent to APIs and received from them

  3. Use HTTPS - Make requests to HTTPS URLs only

  4. Set timeouts - Prevent long-hanging requests from affecting performance:

php
$args = [
'timeout' => 15, // 15 seconds max
];
$response = wp_remote_get($url, $args);
  1. Verify SSL - Keep the sslverify parameter true in production:
php
$args = [
'sslverify' => true, // Default, but good to be explicit
];

Summary

The WordPress HTTP API provides a powerful and standardized way to interact with external services from your plugins. By using functions like wp_remote_get(), wp_remote_post(), and wp_remote_request(), you can:

  • Send data to external APIs
  • Retrieve data from third-party services
  • Interact with web services securely
  • Handle responses and errors gracefully
  • Implement caching for better performance

This built-in functionality helps you develop plugins that integrate with external services without needing to reinvent the wheel or rely on additional libraries.

Additional Resources

Exercises

  1. Create a function that fetches posts from a remote WordPress site using the WordPress REST API.

  2. Build a weather widget that displays the current temperature for a user's location using a free weather API.

  3. Create a contact form that submits data to a third-party CRM system using their API.

  4. Implement a caching system for API responses that invalidates the cache when certain actions occur in WordPress.

  5. Create a function that posts updates to social media platforms whenever a new post is published on your WordPress site.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)