Knowledge
Use the OpenAI API in Laravel
#AI
Adding AI to a Laravel app comes down to a few lines: install the client, store your key, and call the chat endpoint. Here is how to set it up cleanly, stream responses, and keep your key and your bill under control.
Published by Mark van Eijk on July 1, 2026
Updated on July 1, 2026 · 2 minute read
- Install the client
- Store your API key
- Make your first call
- Stream the response
- Handle errors and limits
- Or run it locally
Wiring an LLM into a Laravel app is less work than most people expect. The openai-php/laravel package gives you a typed client and a facade, so calling the chat endpoint is a single method call. Here's a clean setup, from installing the client to streaming responses and keeping your key safe.
Install the client
Pull in the package with Composer:
composer require openai-php/laravel
Then publish its config file:
php artisan vendor:publish --provider="OpenAI\Laravel\ServiceProvider"
That creates config/openai.php, which reads your credentials from the environment.
Store your API key
Put your key in .env — never in code or version control:
OPENAI_API_KEY=sk-your-key-here
The published config already references it, so there's nothing else to wire up:
// config/openai.php
'api_key' => env('OPENAI_API_KEY'),
On a production server, set OPENAI_API_KEY as a real environment variable or a secret rather than shipping the .env. If the key ever leaks, rotate it in your OpenAI dashboard immediately.
Make your first call
With the facade, a chat completion is one call:
use OpenAI\Laravel\Facades\OpenAI;
$response = OpenAI::chat()->create([
'model' => 'gpt-4o-mini',
'messages' => [
['role' => 'system', 'content' => 'You are a concise assistant.'],
['role' => 'user', 'content' => 'Summarise what a reverse proxy does.'],
],
'max_tokens' => 200,
]);
return $response->choices[0]->message->content;
Picking a small model like gpt-4o-mini and capping max_tokens are the two cheapest habits for keeping your bill predictable.
Stream the response
For a chat UI you want text to appear as it's generated rather than after a long pause. Use the streaming variant and emit each chunk:
use OpenAI\Laravel\Facades\OpenAI;
return response()->stream(function () {
$stream = OpenAI::chat()->createStreamed([
'model' => 'gpt-4o-mini',
'messages' => [['role' => 'user', 'content' => 'Write a haiku about servers.']],
]);
foreach ($stream as $chunk) {
echo $chunk->choices[0]->delta->content ?? '';
ob_flush();
flush();
}
}, 200, [
'Content-Type' => 'text/event-stream',
'X-Accel-Buffering' => 'no',
]);
The X-Accel-Buffering: no header matters behind Nginx, which otherwise buffers the whole response and defeats the point of streaming.
Handle errors and limits
Two failures are worth handling explicitly. The first is the rate limit — under load OpenAI returns HTTP 429, and you should back off and retry rather than hammer the endpoint; the dedicated guide is fix the OpenAI API rate limit (429) error. The second is cost: set a hard spending limit in your account, cache repeated prompts, and reach for the smallest model that does the job.
Or run it locally
If you'd rather not depend on a paid API at all, the same code can point at a local model. Ollama exposes an OpenAI-compatible endpoint, so changing the base URL to http://localhost:11434/v1 lets this exact Laravel setup talk to a model running on your own server.
Subscribe to our newsletter
Do you want to receive regular updates with fresh and exclusive content to learn more about web development, hosting, security and performance? Subscribe now!
Frequently asked questions
- Which package should I use to call OpenAI from Laravel?
- The community-maintained openai-php/laravel package is the standard choice. It wraps the openai-php/client, adds a Laravel facade and config file, and reads your key from the environment. Install it with Composer and publish the config, and you have a typed client available app-wide.
- Where should I store my OpenAI API key?
- In your .env file as OPENAI_API_KEY, never in code or version control. Reference it through config/openai.php so it is cached with the rest of your config. On a production server, set it as a real environment variable or a secret, and rotate it if it is ever exposed.
- How do I stream responses so the user sees text as it generates?
- Use the streaming variant of the chat call, which returns an iterator of chunks, and emit each chunk as it arrives from a streamed response. In Laravel that means returning a response()->stream() (or an event stream) and echoing each delta, flushing the buffer so the browser renders it progressively.
- How do I avoid surprise bills from the OpenAI API?
- Set a hard usage limit in your OpenAI account, cache or deduplicate repeated prompts, choose the smallest model that does the job, and cap max_tokens on every request. Also handle rate-limit errors gracefully so a retry storm does not run up usage; see the dedicated guide on fixing the 429 error.