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.

“by 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) end

Create 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.

“by 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.

“by 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:

“by 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/false

Reload an instance in-place, optionally including logs.

“by 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.response

Status constants are available for direct comparisons:

“by Fal::Request::Status::IN_QUEUE Fal::Request::Status::IN_PROGRESS Fal::Request::Status::COMPLETED

Fetch the response payload after completion

Call reload! to populate request.response:

“by

poll until completed

until request.completed? request.reload! sleep 1 end

request.response # => model-specific response body

Cancel a request

Requests that are still in the queue can be cancelled:

“by 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.

“by

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 end

Error 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:

“by begin Fal::Request.create!(endpoint_id: endpoint_id, input: { prompt: “hi” }) rescue Fal::UnauthorizedError # handle invalid/missing FAL_KEY end

Stream 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.

“by 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:

“by 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):

“by Fal::Price.each do |p| puts “#pp.endpoint_id => #pp.unit_price #pp.currency per #pp.unit” end

Collect all prices as an array:

“by prices = Fal::Price.all

Estimate cost

Compute a total cost estimate across endpoints using historical API price or unit price.

Unit price (uses billing units like images/videos):

“by 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):

“by 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:

“by 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):

“by Fal::Model.each do |m| puts m.endpoint_id end

all_models = Fal::Model.all

Search with filters:

“by results = Fal::Model.search(query: “text to image”, status: “active”)

Get a model’s price (memoized):

“by price = model.price price.unit_price # => e.g., 0.025

Run a request for a model (uses the model’s endpoint_id as endpoint_id):

“by 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:

“p .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"].