Skip to main content
openai-php provides two packages for PHP developers: a standalone client and a Laravel integration. Both work seamlessly with Lumenfall’s OpenAI-compatible API.

openai-php/client

The standalone PHP client for OpenAI-compatible APIs.

Installation

composer require openai-php/client

Configuration

<?php

use OpenAI;

$client = OpenAI::factory()
    ->withApiKey($_ENV['LUMENFALL_API_KEY'])
    ->withBaseUri('https://api.lumenfall.ai/openai/v1')
    ->make();

Generate images

<?php

use OpenAI;

$client = OpenAI::factory()
    ->withApiKey($_ENV['LUMENFALL_API_KEY'])
    ->withBaseUri('https://api.lumenfall.ai/openai/v1')
    ->make();

$response = $client->images()->create([
    'model' => 'gemini-3-pro-image',
    'prompt' => 'A serene mountain landscape at sunset with dramatic clouds',
    'n' => 1,
    'size' => '1024x1024',
]);

echo $response->data[0]->url;

Generation options

$response = $client->images()->create([
    'model' => 'gpt-image-1.5',
    'prompt' => 'A beautiful garden with roses',
    'n' => 1,
    'size' => '1792x1024',      // landscape
    'quality' => 'hd',
    'style' => 'natural',
    'response_format' => 'url',
]);

Get base64 response

$response = $client->images()->create([
    'model' => 'gpt-image-1.5',
    'prompt' => 'A cute robot painting',
    'response_format' => 'b64_json',
]);

$base64Image = $response->data[0]->b64_json;

Edit images

<?php

use OpenAI;

$client = OpenAI::factory()
    ->withApiKey($_ENV['LUMENFALL_API_KEY'])
    ->withBaseUri('https://api.lumenfall.ai/openai/v1')
    ->make();

$response = $client->images()->edit([
    'model' => 'gpt-image-1.5',
    'image' => fopen('original.png', 'r'),
    'prompt' => 'Add a rainbow in the sky',
    'n' => 1,
    'size' => '1024x1024',
]);

echo $response->data[0]->url;

With a mask

$response = $client->images()->edit([
    'model' => 'gpt-image-1.5',
    'image' => fopen('original.png', 'r'),
    'mask' => fopen('mask.png', 'r'),
    'prompt' => 'A sunlit indoor lounge area with a pool',
    'n' => 1,
    'size' => '1024x1024',
]);

List models

$response = $client->models()->list();

foreach ($response->data as $model) {
    echo $model->id . PHP_EOL;
}

Error handling

<?php

use OpenAI;
use OpenAI\Exceptions\ErrorException;
use OpenAI\Exceptions\TransporterException;

$client = OpenAI::factory()
    ->withApiKey($_ENV['LUMENFALL_API_KEY'])
    ->withBaseUri('https://api.lumenfall.ai/openai/v1')
    ->make();

try {
    $response = $client->images()->create([
        'model' => 'gemini-3-pro-image',
        'prompt' => 'A beautiful sunset',
    ]);
    echo $response->data[0]->url;
} catch (ErrorException $e) {
    $error = $e->getErrorMessage();
    $code = $e->getErrorCode();

    if ($code === 'AUTHENTICATION_FAILED') {
        echo 'Invalid API key';
    } elseif ($code === 'RATE_LIMITED') {
        echo 'Rate limit exceeded';
    } elseif ($code === 'INSUFFICIENT_BALANCE') {
        echo 'Insufficient balance';
    } else {
        echo "API Error: $error";
    }
} catch (TransporterException $e) {
    echo 'Network error: ' . $e->getMessage();
}

openai-php/laravel

The Laravel integration for openai-php.

Installation

composer require openai-php/laravel
Publish the configuration:
php artisan vendor:publish --provider="OpenAI\Laravel\ServiceProvider"

Configuration

Update config/openai.php:
<?php

return [
    'api_key' => env('LUMENFALL_API_KEY'),
    'base_uri' => 'https://api.lumenfall.ai/openai/v1',
    'organization' => null,
    'request_timeout' => 30,
];
Or use environment variables in .env:
LUMENFALL_API_KEY=lmnfl_your_api_key
OPENAI_BASE_URI=https://api.lumenfall.ai/openai/v1

Generate images

Using the Facade:
<?php

namespace App\Http\Controllers;

use OpenAI\Laravel\Facades\OpenAI;

class ImageController extends Controller
{
    public function generate()
    {
        $response = OpenAI::images()->create([
            'model' => 'gemini-3-pro-image',
            'prompt' => 'A serene mountain landscape at sunset with dramatic clouds',
            'n' => 1,
            'size' => '1024x1024',
        ]);

        return response()->json([
            'url' => $response->data[0]->url
        ]);
    }
}

Using dependency injection

<?php

namespace App\Services;

use OpenAI\Client;

class ImageGenerationService
{
    public function __construct(
        private Client $client
    ) {}

    public function generate(string $prompt, string $model = 'gemini-3-pro-image'): string
    {
        $response = $this->client->images()->create([
            'model' => $model,
            'prompt' => $prompt,
            'n' => 1,
            'size' => '1024x1024',
        ]);

        return $response->data[0]->url;
    }
}

Edit images

<?php

namespace App\Http\Controllers;

use OpenAI\Laravel\Facades\OpenAI;
use Illuminate\Http\Request;

class ImageEditController extends Controller
{
    public function edit(Request $request)
    {
        $request->validate([
            'image' => 'required|image',
            'prompt' => 'required|string',
        ]);

        $response = OpenAI::images()->edit([
            'model' => 'gpt-image-1.5',
            'image' => fopen($request->file('image')->path(), 'r'),
            'prompt' => $request->input('prompt'),
            'n' => 1,
            'size' => '1024x1024',
        ]);

        return response()->json([
            'url' => $response->data[0]->url
        ]);
    }
}

Queued job example

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use OpenAI\Laravel\Facades\OpenAI;
use App\Models\GeneratedImage;

class GenerateImageJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public string $prompt,
        public string $model,
        public int $userId
    ) {}

    public function handle(): void
    {
        $response = OpenAI::images()->create([
            'model' => $this->model,
            'prompt' => $this->prompt,
            'n' => 1,
            'size' => '1024x1024',
        ]);

        GeneratedImage::create([
            'user_id' => $this->userId,
            'prompt' => $this->prompt,
            'model' => $this->model,
            'url' => $response->data[0]->url,
        ]);
    }
}

// Dispatch the job
GenerateImageJob::dispatch(
    prompt: 'A beautiful landscape',
    model: 'gemini-3-pro-image',
    userId: auth()->id()
);

Error handling in Laravel

<?php

namespace App\Http\Controllers;

use OpenAI\Laravel\Facades\OpenAI;
use OpenAI\Exceptions\ErrorException;
use Illuminate\Http\Request;

class ImageController extends Controller
{
    public function generate(Request $request)
    {
        try {
            $response = OpenAI::images()->create([
                'model' => 'gemini-3-pro-image',
                'prompt' => $request->input('prompt'),
            ]);

            return response()->json([
                'url' => $response->data[0]->url
            ]);
        } catch (ErrorException $e) {
            $code = $e->getErrorCode();

            return match ($code) {
                'AUTHENTICATION_FAILED' => response()->json([
                    'error' => 'Invalid API key'
                ], 401),
                'RATE_LIMITED' => response()->json([
                    'error' => 'Rate limit exceeded'
                ], 429),
                'INSUFFICIENT_BALANCE' => response()->json([
                    'error' => 'Insufficient balance'
                ], 402),
                default => response()->json([
                    'error' => $e->getErrorMessage()
                ], 500),
            };
        }
    }
}

Next steps