How to Set JSON Endpoints in WordPress to Access an External API

There’s a lot of JSON-based APIs that only provide access through server-side methods. If you want to use client side javascript with one of these external APIs, you’ll need to have your server access the data and serve it through ajax requests or your own JSON endpoint. Thankfully, this is really easy to do with WordPress.

In this example project, I’ll show how to get shipping rates from the Easy Post API with a custom WordPress endpoint.

To simplify this tutorial, I’m only sending 6 parameters (which is just enough data for Easy Post to return a shipping rate):

  • Package Width
  • Package Height
  • Package Length
  • Package Weight
  • Zip Code of Sender
  • Zip Code of Receiver

Setting Up the JSON Endpoint

First step is to register the route where the JSON data will be served. In this case:

* Sets up a JSON endpoint at /wp-json/easy-post/v1/rates/
function easy_post_api_init() {
$namespace = 'easy-post/v1';
register_rest_route( $namespace, '/rates/', array(
'methods' => 'GET',
'callback' => 'easy_post_return_rates',
) );
add_action( 'rest_api_init', 'easy_post_api_init' );

Displaying the Data

The endpoint route is expecting six pieces of data to be sent as query strings, and it uses that to fetch data from the remote API. If the query strings aren’t present, defaults are used. All the parameters are sanitized to ensure they are integers.

Example URL with query strings:

* Outputs Easy Post data on the JSON endpoint
* Defaults are used if query string data is missing, but you might want to return an error instead.
* Valid URL: /wp-json/easy-post/v1/rates/?zip=78701&width=10&length=10&height=10&weight=10&shipping_zip=78751
function easy_post_return_rates( WP_REST_Request $request ) {
// Default shipping settings
$defaults = array(
'zip' => 78701,
'width' => 10,
'length' => 10,
'height' => 10,
'weight' => 16,
'shipping_zip' => 94105
// Get query strings params from request
$params = $request->get_query_params();
// Ensures all param keys are available
$params = array_replace( $defaults, $params );
// Sanitizes each of the keys
$params = array_map( "absint", $params );
// Creates unique key from values to set or retrieve transient
$key = 'easy_post_' . implode( "_", $params );
* To avoid making the same request multiple times in a short time period
* we store the response as a transient in the WordPress database.
* This data will expire after 10 minutes.
if ( false === ( $data = get_transient( $key ) ) ) {
$data = easy_post_make_request( $params );
$response = new WP_REST_Response( $data );
// Cache for 10 minutes
set_transient( $key, $response, 60 * 10 );
} else {
// Returns cached value
return get_transient( $key );
return $response;

Fetching the Data

The function “easy_post_make_request” is what actually requests the data from the external API. The majority of the code here is just arranging the request into an array that the Easy Post API can process.

* Fetches data from the Easy Post API via wp_remote_post
function easy_post_make_request( $params ) {
$to_address = array(
'zip' => $params['shipping_zip'],
'country' => 'US'
$from_address = array(
'zip' => $params['zip'],
'country' => 'US'
$parcel = array(
'length' => $params['length'],
'width' => $params['width'],
'height' => $params['height'],
'weight' => $params['weight']
$request = array(
'shipment' => array(
'to_address' => $to_address,
'from_address' => $from_address,
'parcel' => $parcel
$args = array(
'method' => 'POST',
'blocking' => true,
'headers' => array(
'Content-Type' => 'application/json'
'timeout' => 15,
'sslverify' => false,
'body' => json_encode( $request )
// Replace the EASYPOST_TEST_API_KEY constant with your own API Key
$api_url = 'https://' . EASYPOST_TEST_API_KEY . '';
$response = wp_remote_post( $api_url, $args );
if ( ! is_wp_error( $response ) ) {
$response = json_decode( $response['body'] );
return $response;

Using the Data

When accessing your endpoint, the JSON data fetched from Easy Post should now appear.

Easy Post API

Need to pull shipping rates into your site dynamically? Now you’re ready to go.

You can view the full file here.

About Devin

I am a developer based in Austin, Texas. I run a little theme shop called DevPress and help manage a WooCommerce shop with Universal Yums. Find me on twitter @devinsays.

2 Responses

  1. Dear Devon,
    Thanks so much for this example! I am a newb working with WP and I have a question. Where would this file live? I assume it should be in the cPanel. Please advise. Thanks so much!

Leave a Reply