How to Integrate Third-Party APIs with PHP: Practical Examples & Automation


At CodeBusters.uk, we believe coding should be clear, practical, and fun. This tutorial shows you how to perform a robust PHP API integration — the kind you can drop into real projects. We’ll cover requests, authentication, JSON parsing, error handling, caching, logging, and a simple automation workflow.

New to working with JSON in PHP? Start here: How to Read and Write JSON Files in PHP (with examples).


1) Why Use APIs in PHP?

  • Reuse reliable services (email, payments, CRM, weather data).
  • Automate workflows — sync data, enrich profiles, or trigger tasks.
  • Enhance apps with live external data.
  • Keep your code modular and maintainable.

2) What You’ll Need

  • PHP 8.x with ext-json and ext-curl enabled.
  • Composer (recommended if you’ll use Guzzle).
  • API credentials (keys, tokens) from the provider.
  • Basic familiarity with HTTP requests and JSON.

Tip: Store secrets in environment variables (e.g. .env) or wp-config.php constants, never in your repo.


3) GET Requests with cURL (JSON)

Use this when you want a lightweight, dependency-free request. It fetches JSON, validates the response, and decodes it safely.

<?php
// api-get.php
declare(strict_types=1);

$url = 'https://api.example.com/data?key=' . urlencode(getenv('API_KEY'));

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);

$response = curl_exec($ch);
if ($response === false) {
    throw new RuntimeException('cURL error: ' . curl_error($ch));
}

$httpStatus = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpStatus < 200 || $httpStatus >= 300) {
    throw new RuntimeException('HTTP status ' . $httpStatus . ' from API');
}

$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);

// Use the decoded array:
print_r($data);

Why this is safe: it sets timeouts, validates status codes, and uses JSON_THROW_ON_ERROR for robust decoding.


4) POST Requests with Guzzle (Auth & Headers)

For larger projects, a modern HTTP client like Guzzle makes code cleaner and adds easier retries and error handling.

composer require guzzlehttp/guzzle
<?php
// api-post-guzzle.php
declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

$client = new Client([
    'base_uri' => 'https://api.example.com/v1/',
    'timeout'  => 10.0,
]);

$apiKey = getenv('API_BEARER');

try {
    $response = $client->request('POST', 'submit', [
        'headers' => [
            'Authorization' => 'Bearer ' . $apiKey,
            'Accept'        => 'application/json',
        ],
        'json' => [
            'userId' => 123,
            'action' => 'check-in',
        ],
    ]);

    $status = $response->getStatusCode();
    if ($status !== 200) {
        throw new RuntimeException('Unexpected status ' . $status);
    }

    $body = (string) $response->getBody();
    $data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);

    echo 'Result: ' . ($data['result'] ?? 'no result');

} catch (GuzzleException $e) {
    error_log('HTTP error: ' . $e->getMessage());
    echo 'Upstream API unavailable.';
} catch (Throwable $t) {
    error_log('App error: ' . $t->getMessage());
    echo 'Something went wrong.';
}

Pro tip: use timeouts, retries, and inspect response headers for rate-limit info.


5) Real-World Automation Workflow

Example pattern: validate input → enrich via API A → cache → push to API B (CRM) → log result.

<?php
// workflow.php
declare(strict_types=1);

function cache_get(string $key): ?array {
    $file = __DIR__ . '/cache/' . sha1($key) . '.json';
    if (!is_file($file)) return null;
    $data = json_decode(file_get_contents($file), true);
    if (!$data || $data['expires'] < time()) return null;
    return $data['payload'];
}

function cache_set(string $key, array $payload, int $ttl = 3600): void {
    $file = __DIR__ . '/cache/' . sha1($key) . '.json';
    if (!is_dir(dirname($file))) mkdir(dirname($file), 0775, true);
    file_put_contents($file, json_encode([
        'expires' => time() + $ttl,
        'payload' => $payload
    ]));
}

$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
if (!$email) die('Invalid email');

$result = cache_get($email) ?? callEnrichmentAPI($email);
cache_set($email, $result, 3600);

if (!empty($result['is_valid'])) {
    $crm = callCrmAPI(['email' => $email, 'name' => $result['name'] ?? '']);
}

file_put_contents('api-log.txt', date('c') . ' | ' . $email . PHP_EOL, FILE_APPEND);

Tip: run scripts like this automatically with a cron job for scheduled automation.


6) Best Practices Checklist

  • Secrets: keep API keys out of Git and public repos.
  • Timeouts: always set them; APIs can hang.
  • Rate limits: respect provider headers, cache responses.
  • Error handling: separate 4xx vs 5xx and log cleanly.
  • Logging: scrub personal data, keep request IDs.
  • Testing: mock API calls in unit tests.

7) Common Pitfalls (and Fixes)

Problem Fix
Leaked API keys Use environment variables; rotate keys.
Rate-limit errors Cache responses; add back-off delay.
JSON parse failure Enable JSON_THROW_ON_ERROR.
No logging Write logs to file with timestamps.
Timeouts not set Add reasonable CURLOPT_TIMEOUT.

8) FAQs

Should I use cURL or Guzzle?

Use cURL for quick, single-file scripts; Guzzle for cleaner code, retries, and better error handling in production projects.

Where do I store API keys?

Environment variables or wp-config.php constants. Never in version control.

How can I avoid rate limits?

Cache responses, batch requests when supported, and add exponential back-off on 429 errors.

What status codes should I handle?

Handle success (2xx), client errors (4xx) and server errors (5xx). Retry only for temporary 429/5xx responses.


Next Steps

  • Wrap calls into a reusable client class (e.g. WeatherClient or CrmClient).
  • Hook scripts into cron jobs or webhooks for automation.
  • Add metrics to monitor latency and success rates.

Want to learn more? Check out How to Read and Write JSON Files in PHP.


Enjoyed this guide? Share it and tag CodeBusters.uk — we improve these tutorials based on real feedback.