1

Edited 07-14-24 to show permission callback in api Edit 2: showed my fatal error

I'm new to making api calls in wordpress. I need to make an api call through the backend to a 3rd party api. I can't do it through the frontend because the 3rd party makes it so I get a CORS error and recommended I make the call through the backend.

I go to my child theme's 'functions.php' file. And I write this code:

function custom_theme_api_init() { register_rest_route('custom-theme/v1', '/data/', array( 'methods' => 'GET', 'callback' => 'make_api_call_to_third_party', 'permission_callback' => 'custom_theme_api_permissions', )); } add_action('rest_api_init', 'custom_theme_api_init'); function make_api_call_to_third_party() { $url = 'https://api.pledge.to/v1/organizations'; $api_key = '{my_api_key}'; $options = array( 'http' => array( 'header' => "Authorization: Bearer $api_key\r\n", 'method' => 'GET', ), ); // Create a stream context //$context = stream_context_create($options); // Make the HTTP GET request //$response = file_get_contents($url, false, $context); // Make the API call $response = wp_remote_get($url, $options); if ($response === false) { // Handle error return false; } // Process the response $data = json_decode($response, true); return new WP_REST_Response($data, 200); } 

and in my frontend, I make a call to the endpoint:

<script> const baseURL = 'https://purgace.com/wp-json/custom-theme/v1/data/'; function getOrgs(){ return fetch(`${baseURL}`) .then(response => response.json()) .then(data =>{ console.log(data) //return renderResults(data.results); }) .catch(error => console.error('Error:', error)); } getOrgs(); </script> 

However, I am receiving this error:

Object code: "rest_no_route" data: {status: 404} message: "No route was found matching the URL and request method." [[Prototype]]: Object 

I think my endpoint could be wrong? I'm not sure. Any ideas on what the problem can be?

I am also now getting a fatal error and it gives me a stack trace:

Fatal error: Uncaught TypeError: json_decode(): Argument #1 ($json) must be of type string, array given in /home/dh_r54n9h/purgace.com/wp-content/themes/divi-child/functions.php:65 Stack Trace 1. json_decode(Array, true) /home/dh_r54n9h/purgace.com/wp-content/themes/divi-child/functions.php:65 2. make_api_call_to_third_party(Object(WP_REST_Request)) /home/dh_r54n9h/purgace.com/wp-includes/rest-api/class-wp-rest-server.php:1230 3. WP_REST_Server->respond_to_request(Object(WP_REST_Request), '/custom-theme/v...', Array, NULL) /home/dh_r54n9h/purgace.com/wp-includes/rest-api/class-wp-rest-server.php:1063 4. WP_REST_Server->dispatch(Object(WP_REST_Request)) /home/dh_r54n9h/purgace.com/wp-includes/rest-api/class-wp-rest-server.php:439 5. WP_REST_Server->serve_request('/custom-theme/v...') /home/dh_r54n9h/purgace.com/wp-includes/rest-api.php:428 6. rest_api_loaded(Object(WP)) /home/dh_r54n9h/purgace.com/wp-includes/class-wp-hook.php:324 7. WP_Hook->apply_filters(NULL, Array) /home/dh_r54n9h/purgace.com/wp-includes/class-wp-hook.php:348 8. WP_Hook->do_action(Array) /home/dh_r54n9h/purgace.com/wp-includes/plugin.php:565 9. do_action_ref_array('parse_request', Array) /home/dh_r54n9h/purgace.com/wp-includes/class-wp.php:418 10. WP->parse_request('') /home/dh_r54n9h/purgace.com/wp-includes/class-wp.php:813 11. WP->main('') /home/dh_r54n9h/purgace.com/wp-includes/functions.php:1336 12. wp() /home/dh_r54n9h/purgace.com/wp-blog-header.php:16 13. require('/home/dh_r54n9h...') /home/dh_r54n9h/purgace.com/index.php:17 14. {main} thrown in /home/dh_r54n9h/purgace.com/wp-content/themes/divi-child/functions.php on line 65 

Any help is appreciated. Thanks in advance! Happy coding :)

13
  • did you flush permalinks or turn permalinks off? Your route registration is also missing the permission_callback, it isn't optional and determines who can and can't see/user the REST API endpoint, there'll be a lot of messages about this in your PHP error logs. You also don't need to use json_encode on $response the REST API automatically encodes the data
    – Tom J Nowell
    CommentedApr 17, 2024 at 19:41
  • Hi @TomJNowell thanks for your message! I did not flush permalinks nor turn permalinks off. I also did not include permission_callback. I will give your recommendations a shot! Thanks again!CommentedApr 17, 2024 at 23:16
  • Actually flushing/resaving permalinks might help! You can also use __return_true as the value for permission callback if you want everyone to be able to use it, saves creating an extra function for it
    – Tom J Nowell
    CommentedApr 18, 2024 at 7:19
  • @TomJNowell thanks for your help! I included the permission callback. However it's still not working. I checked the error logs and i see this message repeatedly:PHP Warning: Constant WP_CACHE already defined in /home/dh_r54n9h/purgace.com/wp-config.php on line 7 . Does this have to do with why the api call isn't working? Thanks again for your help!CommentedJun 4, 2024 at 14:33
  • @TomJNowell im not familiar with flushing/resaving permalinks. Would i do that in the functions.php file?CommentedJun 4, 2024 at 14:36

1 Answer 1

4

So I finally figured out my problems. One mistake I was making was not structuring $options properly.

This is WRONG what i did:

$options = array( 'http' => array( 'header' => "Authorization: Bearer $api_key\r\n", 'method' => 'GET', ), ); 

I'm not supposed to use http. This is the CORRECT WAY to do it:

$options = array( 'headers' => array( 'Authorization' => 'Bearer ' . $api_key, ), 'method' => 'GET', ); 

You have to use headers instead of http when passing in an api key.

Another mistake I made was improperly getting the response from wp_remote_get().

This is the WRONG WAY:

// Make the API call $response = wp_remote_get($url, $options); if ($response === false) { // Handle error return false; } // Process the response $data = json_decode($response, true); return new WP_REST_Response($data, 200); } 

using wp_remote_get() like this is correct:

$response = wp_remote_get($url, $options); 

However, the way i passed the response into json_decode($response, true) is incorrect. I had to extract the response body like this:

This is the CORRECT WAY:

// Extract the response body $body = wp_remote_retrieve_body($response); // Convert the JSON response to an associative array $data = json_decode($body, true); 

After i did this, I could access the data from the api response. Here's my correct code in its entirety:

function make_api_call_to_third_party() { $url = 'https://api.pledge.to/v1/organizations'; $api_key = '{my api key}'; $options = array( 'headers' => array( 'Authorization' => 'Bearer ' . $api_key, ), 'method' => 'GET', ); // Make the API call $response = wp_remote_get($url, $options); //handle error section if (is_wp_error($response)) { $error_message = $response->get_error_message(); // Handle the error, return an error response or log it return new WP_REST_Response(array('error' => $error_message), 500); } // Extract the response body $body = wp_remote_retrieve_body($response); // Log the response for debugging error_log('API response: ' . $body); // Convert the JSON response to an associative array $data = json_decode($body, true); // Check for JSON decoding errors if (json_last_error() !== JSON_ERROR_NONE) { // Handle JSON decoding error return new WP_REST_Response(array('error' => 'Failed to decode JSON response'), 500); } //process the response return new WP_REST_Response($data, 200); } //function for permissions callback function custom_theme_api_permissions(){ return true; } 

I was stuck on this for a really long time. So i hope this helps someone out there. Happy coding everyone :)

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.