DEV Community

Xproapi
Xproapi

Posted on Edited on

How to Integrate a Third-Party REST API in Laravel (With Error Handling and Retries)

How to Integrate a Third-Party REST API in Laravel (With Error Handling and Retries)

Integrating an external API into a Laravel application is usually straightforward. You send an HTTP request, receive JSON, and process the response.

The real challenges appear later.

What happens when the API is temporarily unavailable? What if the server responds with HTTP 429? What if a request takes 30 seconds? And how do you prevent API credentials from ending up in your source code?

In this tutorial, we'll build a small, reusable API integration in Laravel with proper configuration, timeouts, error handling, and retry logic.

1. Store API credentials securely

Never hardcode API keys inside controllers or service classes.

Add the following to your .env file:

EXTERNAL_API_BASE_URL=https://api.example.com
EXTERNAL_API_KEY=your_api_key
Enter fullscreen mode Exit fullscreen mode

Then add a configuration entry in config/services.php:

'external_api' => [
    'base_url' => env('EXTERNAL_API_BASE_URL'),
    'key' => env('EXTERNAL_API_KEY'),
],
Enter fullscreen mode Exit fullscreen mode

This keeps environment-specific configuration outside your application logic.

2. Create a dedicated API service

I prefer keeping external API communication inside a service class instead of scattering HTTP requests throughout controllers.

Create:

php artisan make:class Services/ExternalApiService
Enter fullscreen mode Exit fullscreen mode

Implementation:

<?php

namespace App\Services;

use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\RequestException;

class ExternalApiService
{
    protected function client(): PendingRequest
    {
        return Http::baseUrl(
            config('services.external_api.base_url')
        )
            ->withToken(config('services.external_api.key'))
            ->acceptJson()
            ->timeout(15)
            ->connectTimeout(5);
    }

    public function getUser(string $username): array
    {
        $response = $this->client()->get('/users', [
            'username' => $username,
        ]);

        $response->throw();

        return $response->json();
    }
}
Enter fullscreen mode Exit fullscreen mode

The endpoint and authentication scheme above are examples. Replace them with the actual API contract.

A dedicated service makes the integration easier to test, maintain, and reuse.

3. Handle API failures properly

External APIs can fail for several reasons:

  • Invalid credentials.
  • Invalid parameters.
  • Rate limiting.
  • Temporary upstream failures.
  • Network timeouts.
  • Unexpected response formats.

Don't assume every request will return HTTP 200.

For example:

try {
    $user = app(ExternalApiService::class)
        ->getUser('example');

} catch (\Illuminate\Http\Client\RequestException $e) {

    report($e);

    return response()->json([
        'message' => 'The external service returned an error.',
    ], 502);

} catch (\Illuminate\Http\Client\ConnectionException $e) {

    report($e);

    return response()->json([
        'message' => 'The external service is temporarily unavailable.',
    ], 503);
}
Enter fullscreen mode Exit fullscreen mode

In a production application, you should also distinguish validation errors, authentication failures, and rate-limit responses instead of converting every upstream failure into the same response.

4. Implement retry logic carefully

A temporary network issue doesn't necessarily mean the operation has failed permanently.

Laravel provides retry support through its HTTP client.

For example:

$response = Http::retry(
    3,
    500,
    throw: false
)
    ->timeout(15)
    ->withToken(config('services.external_api.key'))
    ->get('https://api.example.com/users');
Enter fullscreen mode Exit fullscreen mode

This retries failed requests up to three times, with a 500 ms delay.

However, retries should be used carefully.

For HTTP 429 responses, respect the API's Retry-After header when available. Avoid blindly retrying every request. Retrying non-idempotent operations can create duplicate actions.

5. Add logging without exposing secrets

When debugging an API integration, request logs are extremely useful.

You may want to record:

  • Endpoint name.
  • HTTP status.
  • Response time.
  • Request ID.
  • Error category.
  • Timestamp.

Never log API keys, authorization headers, passwords, or sensitive response data.

A simple logging example:

logger()->info('External API request completed', [
    'endpoint' => '/users',
    'status' => $response->status(),
]);
Enter fullscreen mode Exit fullscreen mode

For larger applications, consider using Laravel queues for non-urgent API operations and monitoring failed jobs through Laravel Horizon.

6. Test the integration without calling the real API

Laravel's HTTP testing tools allow you to fake external responses.

use Illuminate\Support\Facades\Http;

Http::fake([
    'api.example.com/*' => Http::response([
        'id' => '123',
        'username' => 'example',
    ], 200),
]);
Enter fullscreen mode Exit fullscreen mode

Now your application can be tested without depending on an external server.

Test at least these cases:

  1. Successful API response.
  2. Invalid API key.
  3. HTTP 429 rate limit.
  4. HTTP 500 response.
  5. Connection timeout.
  6. Invalid JSON response.

7. Where this approach is useful

The same architecture works for many external integrations:

  • Social media APIs.
  • Payment gateways.
  • CRM platforms.
  • Analytics services.
  • Data providers.
  • SaaS integrations.

If you're integrating X-related data into a Laravel application, you can explore API documentation and integration examples at XProAPI.

The important thing is to treat external API communication as a separate application boundary.

Final thoughts

A successful API integration is not just about making an HTTP request.

It's about handling failures, protecting credentials, managing rate limits, logging useful information, and making the integration maintainable.

Build the integration properly once, and you'll have a reusable foundation for every external service your Laravel application needs.


DEV tags: laravel, php, api, webdev, programming

Top comments (0)