# Laravel and the CurrencyCore API

> Add CurrencyCore to Laravel with the Illuminate HTTP client, config/services.php, an environment variable, a timeout, and one controller method.

Canonical: https://currency-core.com/docs/guides/laravel/
Updated: 2026-11-11
Published: 2026-11-11

---
There is no official Laravel or PHP SDK, so the Illuminate HTTP client is the supported path inside Laravel. Put the base URL and key in `config/services.php`, call the API from a small service class, and keep the controller thin. Reading config through `config()` instead of `env()` means `php artisan config:cache` continues to work in production.

The example needs Laravel 10 or later. Free includes 1,000 requests per month at 60 per minute. Live keys require a paid plan; test keys use the same reference data and quota, capped at 60 per minute.

```php
// config/services.php
'currencycore' => [
    'key' => env('CURRENCYCORE_API_KEY'),
    'base_url' => 'https://api.currency-core.com/v1',
],
```

The service wraps one GET, applies a timeout, and returns the upstream status and body:

```php
<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class CurrencyCore
{
    public function convert(string $from, string $to, float $amount): array
    {
        $key = config('services.currencycore.key');
        abort_if(blank($key), 500, 'Set CURRENCYCORE_API_KEY');

        $response = Http::withToken($key)
            ->timeout(10)
            ->acceptJson()
            ->get(config('services.currencycore.base_url') . '/convert', [
                'from' => $from,
                'to' => $to,
                'amount' => $amount,
            ]);

        return [
            'status' => $response->status(),
            'body' => $response->json(),
        ];
    }
}
```

The controller forwards the status so the caller sees `400`, `401`, `403`, or `429` instead of a generic `500`:

```php
<?php

namespace App\Http\Controllers;

use App\Services\CurrencyCore;
use Illuminate\Http\Request;

class CurrencyController extends Controller
{
    public function convert(Request $request, CurrencyCore $currencyCore)
    {
        $result = $currencyCore->convert(
            $request->query('from', 'USD'),
            $request->query('to', 'INR'),
            (float) $request->query('amount', '100'),
        );

        return response()->json($result['body'], $result['status']);
    }
}
```

The response shapes differ by endpoint:

```json
{
  "from": "USD",
  "amount": 100,
  "date": "2026-11-10",
  "results": [{ "to": "INR", "result": 8345.0, "rate": 83.45 }]
}
```

```json
{ "base": "EUR", "date": "2026-11-10", "rates": { "EUR": 1, "USD": 1.0861 } }
```

Use `Http::preventStrayRequests()` in tests so a missing fake fails loudly instead of hitting the network. Cache by `date` and base: historical snapshots are stable for normal caching, while today's value should expire on your business cadence.

## Next steps

- [API reference](/docs/api/) and [OpenAPI specification](/docs/openapi/)
- [Authentication](/docs/authentication/) and [error codes](/docs/errors/)
- [PHP guide](/docs/guides/php/) for a framework-free client
- [All developer guides](/docs/guides/)
