Currently Available: Need a skilled Software Developer for your next project?
Categories
WordPress

How to Cache External API Responses with WordPress Transients

When a WordPress page requests data from an external API, the site sends a network request and waits for the provider’s response. Each repeated request makes the WordPress server and the API provider’s server do more work. A transient is a WordPress cache entry that stores data temporarily and expires after a time you choose. Later requests can reuse the successful response stored in the transient without calling the provider again.

Use set_transient() to save the response and get_transient() to retrieve it. When the cache entry is missing, request fresh data and save it for a limited time. Because WordPress can remove a transient before its expiration time, code must handle a cache miss on every request.

Cache successful GET responses

For API calls that only retrieve data, check the transient first. If it contains data, return it. Otherwise, send a GET request, the HTTP method for retrieving data. Check the response for errors, then cache it if it is valid. The WordPress Transients API provides these storage and retrieval functions.

This example expects the API to return a JSON object or array. Replace the example URL with the URL your provider gives you for its API.

function my_plugin_get_catalog() {
    $url       = 'https://api.example.com/v1/catalog';
    $cache_key = 'my_plugin_catalog_' . md5( $url );

    $cached_data = get_transient( $cache_key );

    // A cached empty array is valid, so check specifically for a cache miss.
    if ( false !== $cached_data ) {
        return $cached_data;
    }

    $response = wp_remote_get( $url );

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

    $status_code = wp_remote_retrieve_response_code( $response );

    if ( $status_code < 200 || $status_code >= 300 ) {
        return new WP_Error(
            'catalog_api_http_error',
            'The catalog API returned an unsuccessful HTTP status.',
            array( 'status' => $status_code )
        );
    }

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

    if ( JSON_ERROR_NONE !== json_last_error() || ! is_array( $data ) ) {
        return new WP_Error(
            'catalog_api_invalid_response',
            'The catalog API did not return a valid JSON object or array.'
        );
    }

    set_transient( $cache_key, $data, HOUR_IN_SECONDS );

    return $data;
}

The strict comparison, false !== $cached_data, distinguishes a cache miss from valid data that PHP treats as false, such as an empty array. This example caches arrays, so it avoids storing the boolean false, which WordPress also uses to signal that a transient is missing.

The function returns a WP_Error, WordPress’s error object, if the request fails. It also returns one if the API reports an unsuccessful status or sends an invalid response. It does not cache these failures, so a later request can try the API again. Code that calls this function should check is_wp_error() before using the result.

Choose an expiration time and cache key

HOUR_IN_SECONDS makes the example’s one-hour cache lifetime readable; WordPress also provides constants such as DAY_IN_SECONDS. Choose a lifetime based on how quickly the API data changes, how often the provider limits requests, and how old the displayed data can reasonably be. The WordPress Transients API introduction explains that the expiration is a maximum lifetime, not a promise that the value will remain available for the full period. Always keep the cache-miss path working.

A transient key must be 172 characters or fewer. The example hashes the URL with md5() so the key stays short. If query parameters or other request details change the response, include those details in the key too. For authenticated requests, do not put a secret token directly in the key; use a stable identifier for the data scope when different credentials produce different results.

Set an expiration every time you call set_transient(). WordPress stores transients in its options table, a database table for WordPress settings, by default. A persistent object cache such as Redis or Memcached can store them in memory instead. The WordPress documentation covers both storage options. The expiration tells WordPress when the cached value is no longer valid, so it does not keep serving old data indefinitely.

Refresh or remove cached data deliberately

Use transients for GET requests that retrieve data. Do not cache POST, PATCH, PUT, or DELETE requests: those methods can change data, so reusing an earlier response can misrepresent the result. The WordPress API integration guidance also recommends limiting this cache pattern to GET requests.

When your code knows that the underlying data changed, call delete_transient( $cache_key ) to remove the cached value before its expiration. For example, a plugin that updates a remote catalog can clear the catalog transient after a successful update. WordPress may leave expired entries in the database until it requests them again; research on transient storage describes how those leftover rows can contribute to database bloat.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Email updates

Usually a new article and a few links I found interesting.

No spam. Unsubscribe with one click.

Leave a Reply

Your email address will not be published. Required fields are marked *