cURL API calls with PHP and json data (GET POST PUT DELETE)

I was recently working on a project were I needed to integrate an external API using HTTP cURL requests. It was my first time doing this and I had a lot of problems figuring this out. I wrote this post so I can remember my cURL API calls for next time, and maybe it can help you as well. 

The API calls and functions I’m using in this post are all working examples on PHP -v 5.6.

REST API calls with cURL, PHP and json

cURL setup

Implementing an external API into your project is probably going to take more than just one API call and from different pages in your project. This is why I’ve created a ‘simple’ PHP script that allows us to call this function, with a set of parameters, and a cURL request will be done.

Make sure to put this code into a file or place that can be accessed by your entire app or website.(I’ve updated this function so we’ll be able to define the headers when we’re making the call. I’ve added a section for custom headers at the bottom!)

function callAPI($method, $url, $data){
   $curl = curl_init();

   switch ($method){
      case "POST":
         curl_setopt($curl, CURLOPT_POST, 1);
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
         break;
      case "PUT":
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);			 					
         break;
      default:
         if ($data)
            $url = sprintf("%s?%s", $url, http_build_query($data));
   }

   // OPTIONS:
   curl_setopt($curl, CURLOPT_URL, $url);
   curl_setopt($curl, CURLOPT_HTTPHEADER, array(
      'APIKEY: 111111111111111111111',
      'Content-Type: application/json',
   ));
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);

   // EXECUTE:
   $result = curl_exec($curl);
   if(!$result){die("Connection Failure");}
   curl_close($curl);
   return $result;
}

This is a basic setup for doing a cURL call and I’m using a switch statement to check if the API call will be a POST, PUT, or something else (get or delete). I’ll go deeper into the switch case while we’re actually doing the specific requests.

I’m using if-statements inside the switch-case to see if we want to provide json data into our call or not. For the POST and PUT request the if-statement is not really necessary because we’re only using POST or PUT with data, but it’s an extra security to make sure our call function won’t break.

cURL GET request

The most simple API call is the GET call, so let’s start with that! Our callAPI function expects 3 parameters: $method, $url and $data. We need to give those parameters to all our API calls, so for a GET we can just set $data on false, because we are not passing any data with a GET call.

$get_data = callAPI('GET', 'https://api.example.com/get_url/'.$user['User']['customer_id'], false);
$response = json_decode($get_data, true);
$errors = $response['response']['errors'];
$data = $response['response']['data'][0];

$get_data already returns all the data we want from the API in a json string. I’m using $response to convert the json string back to a usable PHP array. You can skip those steps if you want, this is my personal preference. I’m also using the extra $errors and $data arrays to store the actual data and errors.

cURL POST request

Obviously, a POST request does require data. Make sure your json-data is correct, otherwise the request will keep returning errors. Although.. If we receive errors from the API, that means our calls are working 😉

In my example I’m using the cakePHP syntax for setting up my json array, so don’t mind that.

$data_array =  array(
      "customer"        => $user['User']['customer_id'],
      "payment"         => array(
            "number"         => $this->request->data['account'],
            "routing"        => $this->request->data['routing'],
            "method"         => $this->request->data['method']
      ),
);

$make_call = callAPI('POST', 'https://api.example.com/post_url/', json_encode($data_array));
$response = json_decode($make_call, true);
$errors   = $response['response']['errors'];
$data     = $response['response']['data'][0];

Because we’re doing an API call with json data, I’m converting my PHP array to a json string with json_encode($data_array);. The response will come in as a json string again, so I’m using json_decode($make_call, true); to convert the json string back to a usable PHP array. Same as we did in our GET call, so you can skip these steps again if you don’t need them.

cURL PUT request

The PUT request is almost the same as the POST request. I had a hard time figuring out how to pass data into a PUT call. If we take a look at our callAPI() function, you see that I changed some things up between the PUT and the POST request. We can still use the same parameters in our callAPI() function as always.

$data_array =  array(
   "amount" => (string)($lease['amount'] / $tenant_count)
);

$update_plan = callAPI('PUT', 'https://api.example.com/put_url/'.$lease['plan_id'], json_encode($data_array));
$response = json_decode($update_plan, true);
$errors = $response['response']['errors'];
$data = $response['response']['data'][0];

cURL DELETE request

The delete request is very simple again. We can just hit the API url with the $id we want to remove and poof… it’s gone forever.

callAPI('DELETE', 'https://api.example.com/delete_url/' . $id, false);

What with flexible headers?

In the beginning we defined our callAPI function with preset headers. But what if we, for some reason, need to change the headers a bit for another call? We don’t want to write a whole new callAPI function just to edit some headers. Therefore, here’s an option on how to make the preset headers flexible:

function callAPI($method, $url, $data, $headers = false){
   $curl = curl_init();

   switch ($method){
      ...
   }

   // OPTIONS:
   curl_setopt($curl, CURLOPT_URL, $url);
   if(!$headers){
       curl_setopt($curl, CURLOPT_HTTPHEADER, array(
          'APIKEY: 111111111111111111111',
          'Content-Type: application/json',
       ));
   }else{
       curl_setopt($curl, CURLOPT_HTTPHEADER, array(
          'APIKEY: 111111111111111111111',
          'Content-Type: application/json',
          $headers
       ));
   }
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);

   // EXECUTE:
   ...
}

There are 2 differences here from our first function. 1: We’ve added an extra parameter in our function to define if we want to use a custom header or not. I put it to $headers = false to give it a default value. Now we’re not required to enter our headers with every call.

The second change is the if-statement when we’re setting the API headers. If we didn’t give in any headers when we make the call, it’s going to use our default headers instead of crashing. Now we’re ready to add custom headers with our call!

In this example, I’m using search parameters to search for specific data before I’ll pull in all the data with the API. To make the search, I obviously need to be able to add my search query into my callAPI headers. Here’s my example:

Creating custom headers before our call

$one_month_ago = date("Y-m-d", strtotime(date("Y-m-d", strtotime(date("Y-m-d"))) . "-1 month"));
$rent_header = 'Search: and[][created][greater]=' . $one_month_ago . '%and[][created][less]=' . date('Y-m-d') . '%';

//the actual call with custom search header
$make_call = callAPI('GET', 'https://api.example.com/get_url/', false, $rent_header);

This is just an example on how to add headers. My example is to get all rows where a rent was paid in the last 30 days. $one_month_ago is just a helper variable. The $rent_header is the actual header I want to add to my default headers. This needs to be a string!!

When you’ve set the header, you can just do a regular api call and add your new header at the end.

I didn’t need to use any other API call methods like patch or purge or anything like that. These you need to figure out yourself. If there’s some magic going on in this post I hope my examples can give you a better understanding.

I recently wrote a part 2 for this post, that will talk about generating an AUTH-key (utoken) before we make our calls. Make sure to check it out here as well!

14 Comments

  • Adam says:

    Thanks, man. this is awesome. although modified it to
    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);

    due to the authentication method am using. Thanks

  • Art3mis9 says:

    I’m coding a web app that needs to use oAuth to fetch data. I can’t send the data from the client, for security reasons, so I need to have the client send the request to our own server first which then will make the API call using the credentials and then take the returned data and send it back to the web client.

    Can I do this using PHP cURL? This is my first development project and I’m new to API’s. I stumbled across your post, and the information is great. I’m just struggling with the implementation.

    • weichie says:

      Hey there! Thanks for commenting. A lot of people ask me how this can be done if you need login credentials first. (Generating an auth-key before making the general API call). I’ll try to make a new Blog post about this problem this week!

  • Kalumba Raymond Joseph says:

    wooow this has really been Interesting to know, it has really helped to to understand how cURL works have been using frame works though at times i has getting changes. thumbs up brother peace…….

  • vincenzo says:

    Hi, many thnaks for your tutorial, I’m connecting to a API using cURL and php, the API returns a id token for a specific user. I don’t understand why if I access directly the request url, for example if I put the login url in the browser then i’m able to open other urls without needing the token again. Is the token saved in the header? Many thanks

  • AK says:

    Thanks bro. This helped.

  • Andrew Dzimano says:

    Great help, however, inside the function I needed these two options below for it to work:
    //additional options
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 20);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

  • Todd Ferguson says:

    THANK YOU SO MUCH, for posting this. Super helpful and best of all… it actually works!!! Great post!

  • vijay says:

    Thanks, Its works like charms.

  • Rue says:

    Hi i am trying to post username and password for log-in to the API but i am getting an error mesage “Notice: Trying to get property of non-object” when i try to log in..may you please help me with a log-in POST request
    thanx

  • PHP Developer says:

    Worked for me like a charm. Thanks for such a nice and useful tutorial.

  • rossi says:

    how dos its work if i need du submit an auth-token for authorization ???

    • weichie says:

      I think you can add the following into the options part of the callAPI function:

      curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
      curl_setopt($curl, CURLOPT_USERPWD, “username:password”);

      Or try flexible headers “Authorization: Token xxxxxxxxxxxxxx” (untested)

  • I really like it wһen peоple get together annd sharе
    opinions. Great sitе, stick ith it!

Leave a Reply

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