Integration guide
Add currency exchange rates and conversion to PHP
Use PHP cURL for server-side requests and cache the latest response until nextUpdateAt. Read the key from the server environment.
1. Get a free API key
Sign up at https://currencyexchangerate-api.com/auth/login, then create a key under API keys in the console. The free plan includes 3,000 requests per month with no credit card. Store the secret as CXR_API_KEY in server-side environment configuration; never expose it in browser code.
.env
shellCXR_API_KEY=cxr_your_secret_key2. Create a reusable client and cache rates
Use the standard HTTP client. Cache every /latest response until nextUpdateAt: rates change at most once by then, and reusing the response saves quota. The helper also exposes /convert.
rates.php
PHP<?php const API_BASE_URL = 'https://api.currencyexchangerate-api.com/api/v1'; function getApi(string $path): array{ $retry = null; $ch = curl_init(API_BASE_URL . $path); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('CXR_API_KEY'), ], CURLOPT_HEADERFUNCTION => function ($curl, $header) use (&$retry) { if (stripos($header, 'Retry-After:') === 0) { $retry = (int) trim(substr($header, 12)); } return strlen($header); }, ]); $body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($body === false) { throw new RuntimeException('Rates API unreachable'); } $data = json_decode($body, true, 512, JSON_THROW_ON_ERROR); if ($status >= 400) { $message = $data['detail'] ?? 'Rates API error'; if ($retry) { $message .= " (retry after $retry seconds)"; } throw new RuntimeException($message, $status); } return $data;} function latest(string $base = 'USD', string $symbols = 'EUR,GBP'): array{ // Per process; use APCu or a framework cache to share across requests. static $saved = []; $id = "$base:$symbols"; if (isset($saved[$id]) && time() < $saved[$id]['until']) { return $saved[$id]['data']; } $query = http_build_query(compact('base', 'symbols')); $data = getApi('/latest?' . $query); $saved[$id] = ['until' => strtotime($data['nextUpdateAt']), 'data' => $data]; return $data;} function convert(string $from, string $to, float $amount): array{ $query = http_build_query(compact('from', 'to', 'amount')); return getApi('/convert?' . $query);}3. Use it in PHP
Call the helper from a server route, controller, view, command, or script. Format converted values for the user’s locale.
convert.php
PHP<?php require 'rates.php'; $result = convert('EUR', 'GBP', 100);$formatter = new NumberFormatter('en_GB', NumberFormatter::CURRENCY);echo $formatter->formatCurrency($result['result'], $result['to']);4. Handle API errors
A 401 means the key is invalid. A 429 can mean a rate limit or quota limit; read Retry-After in seconds before retrying. Other errors use application/problem+json.
errors.php
PHP<?php require 'rates.php'; try { $result = convert('EUR', 'GBP', 100);} catch (RuntimeException $e) { // getCode() is the HTTP status: 401 bad key, 429 limited. http_response_code($e->getCode() === 429 ? 429 : 502); echo $e->getMessage();}5. Format the amount for display
Use locale-aware currency formatting instead of adding a symbol manually.
format.php
PHP<?php // Requires the intl extension.$formatter = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);echo $formatter->formatCurrency(85.249105, 'EUR');