Fal
Installation
Install the gem and add to the application"s Gemfile by executing:
$ bundle add fal
If bundler is not being used to manage dependencies, install the gem by executing:
$ gem install fal
Usage
Configuration
Configure the client once at boot (e.g., in Rails an initializer) using Fal.configure.
Fal.configure do |config|
config.api_key = "your-key" # Optional. Defaults to ENV["FAL_KEY"] if not set.
config.queue_base = "https://queue.fal.run" # Optional (default: https://queue.fal.run)
config.sync_base = "https://fal.run" # Optional (default: https://fal.run)
config.api_base = "https://api.fal.ai/v1" # Optional (default: https://api.fal.ai/v1)
config.request_timeout = 120 # Optional (default: 120)
endCreate a queued request
The Queue API is the recommended way to call models on fal. Provide a endpoint_id in "namespace/name" format and an input payload.
endpoint_id = "fal-ai/fast-sdxl"
request = Fal::Request.create!(
endpoint_id: endpoint_id,
input: { prompt: "a cat" }
)
request.id # => request_id from fal
request.status # => "IN_QUEUE" | "IN_PROGRESS" | "COMPLETED"You can also specify a webhook URL to be notified when the request is finished.
request = Fal::Request.create!(
endpoint_id: endpoint_id,
input: { prompt: "a cat playing piano" },
webhook_url: "https://example.com/fal/webhook"
)Get request status (find and reload)
Fetch the current status by id:
status = Fal::Request.find_by!(id: request.id, endpoint_id: endpoint_id)
status.in_queue? # => true/false
status.in_progress? # => true/false
status.completed? # => true/falseReload an instance in-place, optionally including logs.
request.reload! # refreshes state
request.reload!(logs: true)
request.logs # => array of log entries (if provided by model and logs=1)
# When status is COMPLETED, reload! will also fetch and set request.responseStatus constants are available for direct comparisons:
Fal::Request::Status::IN_QUEUE
Fal::Request::Status::IN_PROGRESS
Fal::Request::Status::COMPLETEDFetch the response payload after completion
Call reload! to populate request.response:
# poll until completed
until request.completed?
request.reload!
sleep 1
end
request.response # => model-specific response bodyCancel a request
Requests that are still in the queue can be cancelled:
request.cancel! # => { "status" => "CANCELLATION_REQUESTED" }Webhooks
fal can POST a webhook to your server when a request completes. Use Fal::WebhookRequest to parse the incoming payload.
# rails controller example
class FalWebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
webhook = Fal::WebhookRequest.from_rack_request(request)
if webhook.success?
# webhook.response contains the model-specific payload
# webhook.logs, webhook.metrics may also be present
head :ok
else
Rails.logger.error("fal webhook error: #{webhook.error} detail=#{webhook.error_detail}")
head :ok
end
end
endError handling
HTTP and API errors raise typed exceptions:
-
Fal::UnauthorizedError(401) -
Fal::ForbiddenError(403) -
Fal::NotFoundError(404) -
Fal::ServerError(other non-success)
Rescue them as needed:
begin
Fal::Request.create!(endpoint_id: endpoint_id, input: { prompt: "hi" })
rescue Fal::UnauthorizedError
# handle invalid/missing FAL_KEY
endStream synchronous responses
Use stream! for SSE streaming from synchronous endpoints. It yields each chunk’s data Hash and returns a Fal::Request whose response contains the last chunk’s payload.
endpoint_id = "fal-ai/flux/dev"
last = Fal::Request.stream!(endpoint_id: endpoint_id, input: { prompt: "a cat" }) do |chunk|
# chunk is a Hash, e.g. { images: [...] }
puts chunk
end
last.completed? # => true/false
last.response # => last streamed data hash (e.g., { "response" => { ... } } or final payload)Pricing
Use the Platform API to fetch per-endpoint pricing.
Find pricing for a single endpoint:
price = Fal::Price.find_by(endpoint_id: "fal-ai/flux/dev")
price.unit_price # => e.g., 0.025
price.unit # => e.g., "image"
price.currency # => e.g., "USD"Iterate through all prices (auto-paginates):
Fal::Price.each do |p|
puts "#{p.endpoint_id} => #{p.unit_price} #{p.currency} per #{p.unit}"
endCollect all prices as an array:
prices = Fal::Price.allEstimate cost
Compute a total cost estimate across endpoints using historical API price or unit price.
Unit price (uses billing units like images/videos):
estimate = Fal::PriceEstimate.create(
estimate_type: Fal::PriceEstimate::EstimateType::UNIT_PRICE,
endpoints: [
# You can pass unit_quantity directly
Fal::PriceEstimate::Endpoint.new(endpoint_id: "fal-ai/flux/dev", unit_quantity: 50),
# Or use call_quantity as a convenience alias for units
Fal::PriceEstimate::Endpoint.new(endpoint_id: "fal-ai/flux-pro", call_quantity: 25)
]
)
estimate.estimate_type # => "unit_price"
estimate.total_cost # => e.g., 1.88
estimate.currency # => "USD"Historical API price (uses calls per endpoint):
estimate = Fal::PriceEstimate.create(
estimate_type: Fal::PriceEstimate::EstimateType::HISTORICAL_API_PRICE,
endpoints: [
Fal::PriceEstimate::Endpoint.new(endpoint_id: "fal-ai/flux/dev", call_quantity: 100)
]
)Models
List, search, and find models via the Models API.
Find a model by endpoint ID:
model = Fal::Model.find_by(endpoint_id: "fal-ai/flux/dev")
model.endpoint_id # => "fal-ai/flux/dev"
model.display_name # => e.g., "FLUX.1 [dev]"
model.category # => e.g., "text-to-image"
model.status # => "active" | "deprecated"
model.tags # => ["fast", "pro"]
model.model_url # => "https://fal.run/..."
model.thumbnail_url # => "https://..."Iterate or collect all models (auto-paginates):
Fal::Model.each do |m|
puts m.endpoint_id
end
all_models = Fal::Model.allSearch with filters:
results = Fal::Model.search(query: "text to image", status: "active")Get a model’s price (memoized):
price = model.price
price.unit_price # => e.g., 0.025Run a request for a model (uses the model's endpoint_id as endpoint_id):
request = model.run(input: { prompt: "a cat" })Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.
For local development, copy the example environment file and set your API key so bin/console can load it automatically:
cp .env.example .env
echo 'FAL_KEY=your_api_key_here' >> .env
The console uses dotenv to load .env, so Fal.configure will default to ENV["FAL_KEY"].