cjmellor / fal-ai-laravel
A Laravel SDK for Fal.ai
Requires
- php: ^8.4
- illuminate/support: ^12.0
- saloonphp/saloon: ^3.0
Requires (Dev)
- driftingly/rector-laravel: ^2.0
- larastan/larastan: ^3.0
- laravel/pail: ^1.2
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- phpstan/phpstan: ^2.0
- rector/rector: ^2.0
README
Fal.ai Laravel Package
A Laravel package for integrating with the Fal.ai API, providing a fluent interface for AI model interactions with built-in webhook support.
Features
- ๐ Fluent API - Chainable methods for easy request building
- ๐ Webhook Support - Secure webhook handling with ED25519 signature verification
- โก Queue & Sync Modes - Support for both immediate and queued requests
- ๐ก๏ธ Security - Built-in webhook verification middleware
- ๐งช Well Tested - Comprehensive test suite
- ๐ Laravel Integration - Native Laravel middleware and service provider
- ๐ฃ๏ธ Built-in Routes - Pre-configured webhook endpoints ready to use
Installation
Install the package via Composer:
composer require fal-ai/laravel
Publish the configuration file:
php artisan vendor:publish --provider="FalAi\FalAiServiceProvider"
Add your Fal.ai API key to your .env
file:
FAL_API_KEY=your_fal_api_key_here
Basic Usage
Simple Request
use FalAi\FalAi; $falAi = new FalAi(); $response = $falAi->model('fal-ai/flux/schnell') ->prompt('A beautiful sunset over mountains') ->imageSize('landscape_4_3') ->run();
Queue vs Sync Modes
Tip
Queue mode is the default and recommended for most use cases. It's perfect for complex generations that take time to process.
Queue Mode (Default)
$response = $falAi->model('fal-ai/flux/dev') ->prompt('A futuristic cityscape') ->queue() // Explicit queue mode (optional, it's the default) ->run(); // Returns: ['request_id' => 'req_123...', 'status' => 'IN_QUEUE']
Use queue mode when:
- Generating high-quality images with many inference steps
- Processing multiple images in batch
- You don't need immediate results
- Working with complex prompts or large image sizes
Sync Mode
$response = $falAi->model('fal-ai/flux/schnell') ->prompt('A beautiful landscape') ->sync() // Switch to sync mode ->run(); // Returns the complete result immediately
Use sync mode when:
- You need immediate results
- Generating simple images with few inference steps
- Building interactive applications
- Testing and development
Warning
Sync mode may timeout for complex requests. Use queue mode for production applications.
Webhook Support
Making Requests with Webhooks
When you add a webhook URL to your request, it automatically switches to queue mode:
$response = $falAi->model('fal-ai/flux/schnell') ->withWebhook('https://myapp.com/webhooks/fal') ->prompt('A beautiful sunset over mountains') ->imageSize('landscape_4_3') ->run(); // Returns: ['request_id' => 'req_123...', 'status' => 'IN_QUEUE']
Webhook URL Requirements
- Must be a valid HTTPS URL
- Must be publicly accessible
- Should respond with 2xx status codes
Setting Up Webhook Endpoints
You have two options for handling webhooks: use the built-in route or create your own custom endpoint.
Option 1: Built-in Webhook Route (Easiest)
The package includes a pre-configured webhook route at /webhooks/fal
that handles basic webhook processing:
// This route is automatically registered by the package // POST /webhooks/fal // Use it in your requests: $response = $falAi->model('fal-ai/flux/schnell') ->withWebhook(url('/webhooks/fal')) // Uses the built-in route ->prompt('Your prompt here') ->run();
Tip
The built-in route automatically verifies webhooks and returns appropriate responses. Perfect for getting started quickly!
Option 2: Custom Webhook Endpoint (Recommended for Production)
use FalAi\Middleware\VerifyFalWebhook; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::post('/webhooks/fal', function (Request $request) { $payload = $request->json()->all(); if ($payload['status'] === 'OK') { $images = $payload['data']['images']; // Process successful results foreach ($images as $image) { // Save image URL: $image['url'] } } elseif ($payload['status'] === 'ERROR') { $error = $payload['error']; // Handle error } return response()->json(['status' => 'processed']); })->middleware(VerifyFalWebhook::class);
For production applications, create a custom webhook endpoint with your own processing logic:
use FalAi\Middleware\VerifyFalWebhook; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::post('/webhooks/fal-custom', function (Request $request) { $payload = $request->json()->all(); if ($payload['status'] === 'OK') { $images = $payload['data']['images']; // Process successful results foreach ($images as $image) { // Save image URL: $image['url'] // Custom processing logic here } } elseif ($payload['status'] === 'ERROR') { $error = $payload['error']; // Handle error with custom logic } return response()->json(['status' => 'processed']); })->middleware(VerifyFalWebhook::class);
Option 3: Manual Verification (Advanced)
For complete control over the verification process:
use FalAi\Services\WebhookVerifier; use FalAi\Exceptions\WebhookVerificationException; Route::post('/webhooks/fal-manual', function (Request $request) { $verifier = new WebhookVerifier(); try { $verifier->verify($request); // Webhook is valid, process payload $payload = $request->json()->all(); return response()->json(['status' => 'verified']); } catch (WebhookVerificationException $e) { return response()->json([ 'error' => 'Unauthorized', 'message' => 'Webhook verification failed' ], 401); } });
Webhook Payload Examples
Successful Completion
{ "request_id": "req_123456789", "status": "OK", "data": { "images": [ { "url": "https://fal.media/files/generated-image.jpg", "width": 1024, "height": 768, "content_type": "image/jpeg" } ], "seed": 12345, "has_nsfw_concepts": [false], "prompt": "A beautiful sunset over mountains" } }
Error
{ "request_id": "req_123456789", "status": "ERROR", "error": { "type": "ValidationError", "message": "Invalid prompt provided" } }
โ๏ธ Configuration
Note
You can customise the package behaviour by publishing and modifying the configuration file.
The configuration file config/fal-ai.php
contains the following options:
return [ 'api_key' => env('FAL_API_KEY'), 'base_url' => 'https://queue.fal.run', 'default_model' => '', 'webhook' => [ // JWKS cache TTL in seconds (max 24 hours) 'jwks_cache_ttl' => env('FAL_WEBHOOK_JWKS_CACHE_TTL', 86400), // Timestamp tolerance in seconds (prevents replay attacks) 'timestamp_tolerance' => env('FAL_WEBHOOK_TIMESTAMP_TOLERANCE', 300), // HTTP timeout for JWKS fetching 'verification_timeout' => env('FAL_WEBHOOK_VERIFICATION_TIMEOUT', 10), ], ];
Environment Variables
# Required FAL_API_KEY=your_fal_api_key_here # Optional webhook configuration FAL_WEBHOOK_JWKS_CACHE_TTL=86400 FAL_WEBHOOK_TIMESTAMP_TOLERANCE=300 FAL_WEBHOOK_VERIFICATION_TIMEOUT=10
Available Models
The package supports all Fal.ai models. Some popular ones include:
FLUX Models (Recommended):
fal-ai/flux/schnell
- Fast image generation (1-4 steps)fal-ai/flux/dev
- High-quality image generation (12B parameters)fal-ai/flux/pro
- Professional grade (API only)fal-ai/flux-lora
- FLUX with LoRA support
Other Popular Models:
fal-ai/stable-diffusion-v35-large
- Latest Stable Diffusion 3.5fal-ai/recraft/v3
- Vector art and typographyfal-ai/aura-flow
- High-quality text-to-imagefal-ai/ideogram/v2
- Excellent typography handling
Fluent API Methods
Common Methods
$request = $falAi->model('fal-ai/flux/schnell') ->prompt('Your prompt here') // Set the text prompt ->imageSize('landscape_4_3') // Set image dimensions ->numImages(2) // Number of images to generate ->seed(12345) // Set random seed ->withWebhook('https://...') // Add webhook URL ->queue() // Use queue mode ->sync(); // Use sync mode
Error Handling
Important
Always implement proper error handling in production applications to gracefully handle API failures and webhook verification issues.
use FalAi\Exceptions\WebhookVerificationException; use InvalidArgumentException; try { $response = $falAi->model('fal-ai/flux/schnell') ->withWebhook('https://myapp.com/webhook') ->prompt('Test prompt') ->run(); if (!$response->successful()) { throw new Exception('API request failed: ' . $response->body()); } } catch (InvalidArgumentException $e) { // Invalid webhook URL or other validation errors echo "Validation error: " . $e->getMessage(); } catch (WebhookVerificationException $e) { // Webhook verification failed (in webhook endpoints) echo "Webhook error: " . $e->getMessage(); } catch (Exception $e) { // Other errors (network, API, etc.) echo "Error: " . $e->getMessage(); }
๐งช Testing
Run the test suite:
composer test
๐ Security
Caution
Webhook security is critical for protecting your application from malicious requests. Always use the provided verification mechanisms.
Webhook Security
This package implements Fal.ai's webhook verification using:
- ED25519 signature verification using Fal.ai's public keys
- Timestamp validation to prevent replay attacks
- JWKS caching for performance
- Automatic header extraction and validation
Best Practices
Tip
Follow these security practices to ensure your webhook endpoints are secure:
- Always use HTTPS for webhook URLs
- Use the provided middleware for automatic verification
- Validate webhook payloads in your application logic
- Implement proper error handling and logging
- Monitor webhook endpoints for suspicious activity
- Use rate limiting on webhook routes
- Keep your API keys secure and rotate them regularly
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
๐ License
This package is open-sourced software licensed under the MIT license.
๐ฌ Support
For support, please open an issue on GitHub or contact the maintainers.