Working with external APIs from PHP using cURL and HTTP clients. Your app will call payment gateways, geocoders, Slack webhooks, and REST APIs. PHP can do that natively or via Guzzle.
cURL GET request
$ch = curl_init('https://api.example.com/v1/rates?base=GBP');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false || $status >= 400) {
throw new RuntimeException('API request failed');
}
$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
POST with JSON body
$payload = json_encode(['message' => 'Hello from PHP'], JSON_THROW_ON_ERROR);
$ch = curl_init('https://api.example.com/v1/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
],
]);
Wrap in a service class
<?php
declare(strict_types=1);
namespace AppServices;
class ExchangeRateClient
{
public function __construct(
private string $apiKey,
private string $baseUrl = 'https://api.example.com/v1'
) {}
public function rate(string $from, string $to): float
{
$url = sprintf('%s/rates?from=%s&to=%s', $this->baseUrl, urlencode($from), urlencode($to));
// curl, decode, return float
return 1.17; // example
}
}
Guzzle (optional)
Guzzle is the common Composer choice for HTTP. Same ideas, cleaner API:
composer require guzzlehttp/guzzle
Error handling and timeouts
- Always set a timeout – hung APIs hang your page
- Log failures with status code and response body (trim secrets)
- Cache read-heavy responses when the API allows it
- Never embed API keys in client-side JavaScript
External APIs fail. Plan for timeouts, retries sparingly, and clear messages when data is temporarily unavailable.

