Calling a web API from PHP with cURL and reading the JSON reply

To talk to an API from PHP you use cURL: open a request, send it, read the status code (200, 401, 404…) and only then decode the JSON in the reply. Most problems come from skipping the second step: the code assumes it went well and treats an error message as data.

A complete GET request

This example goes to a sample address (api.example.com), sends the key in a header and checks everything that can go wrong:

<?php
$ch = curl_init('https://api.example.com/v1/products');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT        => 20,
  CURLOPT_HTTPHEADER     => [
    'Accept: application/json',
    'Authorization: Bearer ' . $key,
  ],
]);
$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error  = curl_error($ch);
curl_close($ch);

if ($body === false) { /* network failure: $error says why */ }
elseif ($status !== 200) { /* the API answered, but with an error */ }
else { $data = json_decode($body, true); }

Sending data (a JSON POST)

To send JSON you add three things to the request: the method, the body, and the header that tells the other side what is inside.

CURLOPT_POST       => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],

What each reply means

Status or symptom It means What to do
curl_exec returns false The request never arrived or did not finish. Read curl_error(): timed out, name does not resolve, connection refused.
401 or 403 The key is missing, wrong or not allowed. Check the authorisation header and the key’s permissions at the service.
404 The request address is wrong. Compare with the API documentation, including the version in the path.
429 You made too many requests. Wait and slow down. Do not retry in a tight loop.
500 or 502 The fault is on the other side. Try later; keep the request so you can repeat it.
200, but json_decode gives null The reply is not valid JSON. See what is wrong with the JSON.
Never switch off certificate checking just to make it pass. Setting CURLOPT_SSL_VERIFYPEER to false silences the error and leaves the request open to anyone in the path. A certificate error (cURL 60) is fixed with the right name in the address or with the certificate on the other side, not with this.
The API key is a password. Do not write it into the code or publish it in a repository: keep it in a file outside the public folder (.env files and permissions). Whoever has it makes requests in your name, and many APIs charge per request.
“Call to undefined function curl_init()”? The cURL extension is not switched on for that PHP version: enable it in Select PHP Version (switching a PHP extension on). And always set a timeout: without one, a slow API holds your script until PHP cuts it off.

The call fails and the cURL message means nothing to you? Send us the error text and the PHP version, without the API key.

Open a support ticket

SEE ALSO

json_decode returns null: what is wrong with the JSON

Keeping passwords out of your PHP code: .env files

Connecting to MySQL from PHP: mysqli and PDO

Where the PHP error log is

RECOMMENDED PRODUCT

Web hosting with cPanel

Domain and SSL included, daily backups and the panel you already know. from $6.60/mo (3-year plan, with coupon)

See plans
  • 0 Users Found This Useful
Was this answer helpful?