1. Go to this page and download the library: Download marceloeatworld/falai-php library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
marceloeatworld / falai-php example snippets
use MarceloEatWorld\FalAI\FalAI;
$fal = new FalAI('your-api-key');
// Synchronous execution
$result = $fal->run('fal-ai/flux/schnell', [
'prompt' => 'a sunset over mountains',
'image_size' => 'landscape_16_9',
]);
$images = $result->json('images');
$stream = $fal->stream('fal-ai/flux/dev', [
'prompt' => 'a sunset over mountains',
]);
foreach ($stream as $event) {
// Event shape depends on the model. flux/dev sends intermediate previews as
// data: URIs in $event['images'][0]['url'], then the final CDN URL.
echo count($event['images']), " image(s) so far\n";
}
$final = $stream->getReturn(); // same payload as run(): images, seed, timings, ...
$url = $final['images'][0]['url'];
// Submit a job
$job = $fal->queue->submit('fal-ai/flux/schnell', [
'prompt' => 'a sunset over mountains',
]);
echo $job->requestId;
// Check status
$status = $fal->queue->status('fal-ai/flux/schnell', $job->requestId);
echo $status->status->value; // IN_QUEUE, IN_PROGRESS, COMPLETED
echo $status->queuePosition; // position in queue (if queued)
// Get result when completed
$result = $fal->queue->result('fal-ai/flux/schnell', $job->requestId);
$images = $result->json('images');
// Cancel a job (202 CANCELLATION_REQUESTED; throws on 400 ALREADY_COMPLETED or 404 NOT_FOUND)
$fal->queue->cancel('fal-ai/flux/schnell', $job->requestId);
use MarceloEatWorld\FalAI\Data\QueueStatus;
$result = $fal->queue->subscribe('fal-ai/flux/schnell', [
'prompt' => 'a sunset over mountains',
], pollInterval: 500, timeout: 300, requestTimeout: 120, onStatus: function (QueueStatus $status) {
echo "Status: {$status->status->value}\n";
foreach ($status->logs as $log) {
echo " {$log['message']}\n";
}
});
$images = $result->json('images');
$job = $fal->queue->submit('fal-ai/flux/schnell', ['prompt' => 'a sunset over mountains']);
foreach ($fal->queue->streamStatus('fal-ai/flux/schnell', $job->requestId) as $status) {
echo "{$status->status->value}\n";
}
$result = $fal->queue->result('fal-ai/flux/schnell', $job->requestId);
$job = $fal->queue->submit('fal-ai/flux/schnell', [
'prompt' => 'a sunset over mountains',
], webhook: 'https://your.app/webhook');
// Laravel controller
public function webhook(Request $request, FalAI $fal)
{
if (! $fal->webhooks()->isValid($request->getContent(), $request->headers->all())) {
abort(401);
}
$payload = $request->json()->all();
// $payload['status'] is "OK" or "ERROR", $payload['payload'] holds the result
}
// Native PHP
use MarceloEatWorld\FalAI\Webhooks\WebhookVerifier;
use MarceloEatWorld\FalAI\Exceptions\WebhookVerificationException;
$verifier = new WebhookVerifier();
try {
$verifier->verify(file_get_contents('php://input'), getallheaders());
} catch (WebhookVerificationException $e) {
http_response_code(401);
exit;
}
use MarceloEatWorld\FalAI\Data\ObjectLifecycle;
$url = $fal->storage->upload('/path/to/input.png', lifecycle: ObjectLifecycle::expiresIn(3600));
use MarceloEatWorld\FalAI\Data\ObjectLifecycle;
// Delete generated files after one hour
$result = $fal->run('fal-ai/flux/schnell', ['prompt' => 'a sunset'], lifecycle: ObjectLifecycle::expiresIn(3600));
// Private: only the owner (and the listed fal.ai nicknames) can read the files
$result = $fal->run('fal-ai/flux/schnell', ['prompt' => 'a sunset'], lifecycle: ObjectLifecycle::private(['alice']));
// Full control over the initial ACL: "default" is "allow", "forbid" (403) or "hide" (404)
$lifecycle = new ObjectLifecycle(
expirationSeconds: 86400,
initialAcl: ['default' => 'forbid', 'rules' => [['user' => 'alice', 'decision' => 'allow']]],
);
use MarceloEatWorld\FalAI\Enums\ModelStatus;
// Search with filters, cursor-based pagination
$page = $fal->models->list(query: 'flux', category: 'text-to-image', status: ModelStatus::Active, limit: 20);
foreach ($page->models as $model) {
echo "{$model->endpointId}: {$model->displayName} ({$model->category})\n";
}
if ($page->hasMore) {
$next = $fal->models->list(query: 'flux', cursor: $page->nextCursor);
}
// Single model (null when unknown)
$model = $fal->models->get('fal-ai/flux/dev');
echo $model->description;
echo $model->licenseType; // commercial, research, ...
print_r($model->metadata); // full raw metadata
// Include the model's OpenAPI schema (input/output parameters)
$model = $fal->models->get('fal-ai/flux/dev', expand: ['openapi-3.0']);
print_r($model->openapi);
// Unit prices, keyed by endpoint id
$prices = $fal->models->pricing('fal-ai/flux/dev', 'fal-ai/flux/schnell');
echo $prices['fal-ai/flux/dev']->unitPrice; // 0.025
echo $prices['fal-ai/flux/dev']->unit; // "megapixels", "image", "video", "second", ...
echo $prices['fal-ai/flux/dev']->currency; // "USD"
// Estimate from expected API calls (based on your historical usage)
$estimate = $fal->models->estimateByCalls([
'fal-ai/flux/dev' => 100,
'fal-ai/flux/schnell' => 500,
]);
echo $estimate->totalCost; // 5.75
echo $estimate->currency; // "USD"
// Estimate from billing units (images, videos, seconds, ...)
$estimate = $fal->models->estimateByUnits([
'fal-ai/flux/dev' => 250,
]);
use MarceloEatWorld\FalAI\Data\ObjectLifecycle;
use MarceloEatWorld\FalAI\Enums\Priority;
$job = $fal->queue->submit('fal-ai/flux/schnell', [
'prompt' => 'test',
],
webhook: 'https://your.app/webhook', // ?fal_webhook=
timeout: 300, // X-Fal-Request-Timeout (seconds before processing must start, else 504)
priority: Priority::Low, // X-Fal-Queue-Priority: normal (default) or low
runnerHint: 'session-abc', // X-Fal-Runner-Hint: route to the same runner (session affinity)
noRetry: true, // X-Fal-No-Retry: disable the automatic retries
lifecycle: ObjectLifecycle::expiresIn(3600), // X-Fal-Object-Lifecycle-Preference
storeIo: false, // X-Fal-Store-IO: 0, do not keep request payloads for 30 days
maxQueueLength: 100, // ?fal_max_queue_length=: reject with 429 if more requests are already waiting
);
$this->app->singleton(\MarceloEatWorld\FalAI\FalAI::class, function () {
return new \MarceloEatWorld\FalAI\FalAI(config('services.falai.api_key'));
});
use MarceloEatWorld\FalAI\FalAI;
public function generate(FalAI $fal)
{
$result = $fal->queue->subscribe('fal-ai/flux/schnell', [
'prompt' => 'A mountain landscape',
]);
return $result->json('images');
}
use MarceloEatWorld\FalAI\Exceptions\QueueFailedException;
use MarceloEatWorld\FalAI\Exceptions\QueueTimeoutException;
use Saloon\Exceptions\Request\RequestException;
try {
$result = $fal->run('fal-ai/flux/schnell', ['prompt' => 'test']);
} catch (RequestException $e) {
echo $e->getResponse()->status();
echo $e->getResponse()->body();
}
try {
$result = $fal->queue->subscribe('fal-ai/flux/schnell', ['prompt' => 'test']);
} catch (QueueTimeoutException $e) {
echo "Timed out: {$e->requestId}"; // the job may still complete server-side
} catch (QueueFailedException $e) {
echo "Failed: {$e->getMessage()}";
} catch (RequestException $e) {
echo $e->getResponse()->json('detail.0.msg'); // validation error from the model
}
bash
composer
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.