# fal models

> Original: https://api.6io.io/en/docs/fal/ (HTML). All pages: https://api.6io.io/llms.txt

The `fal` group opens the fal catalog: images, video, audio and other models. A model name is `fal/<the model id at fal>`, for example `fal/fal-ai/flux/schnell`. Generation runs as a task: the request returns an ID at once, with it you learn the status and collect the result when it is ready. fal calls this a queue, hence `queue` in the addresses. The addresses start with `https://api.6io.io/native/fal`, the authorization is the same: `Authorization: Bearer sixio_sk_...`.

The body of the task goes to fal as it is. The fields of a model are on its page at fal.ai, the API tab: `https://fal.ai/models/<model id>/api`, for example [fal-ai/flux/schnell](https://fal.ai/models/fal-ai/flux/schnell/api).

## A full example

```python
import time
import requests

API = "https://api.6io.io/native/fal"
H = {"Authorization": "Bearer sixio_sk_..."}
MODEL = "fal-ai/flux/schnell"

# 1. the price of a unit (optional)
print(requests.get(f"{API}/price/{MODEL}", headers=H).json())

# 2. submit the task
job = requests.post(
    f"{API}/queue/{MODEL}",
    headers=H,
    json={"prompt": "a red circle on white background", "image_size": {"width": 1024, "height": 1024}},
).json()

# 3. wait until the status becomes COMPLETED
while True:
    st = requests.get(job["status_url"], headers=H).json()
    if st["status"] == "COMPLETED":
        break
    time.sleep(2)

# 4. collect the result
if st.get("error"):
    raise RuntimeError(st["error"])
result = requests.get(job["response_url"], headers=H).json()
print(result["images"][0]["url"])
```

Download the file at once or save the link: file links are valid for a limited time (see below).

## Catalog and price

```bash
curl "https://api.6io.io/native/fal/models?q=flux&limit=5" -H "Authorization: Bearer sixio_sk_..."
curl "https://api.6io.io/native/fal/price/fal-ai/flux/schnell" -H "Authorization: Bearer sixio_sk_..."
```

The catalog is big, so it is paged: search by `q` and take the next page by `next_cursor`.

The answer about the price:

```json
{
  "id": "fal/fal-ai/flux/schnell",
  "currency": "credits",
  "unit": "megapixels",
  "price_per_unit": "0.240000000000",
  "note": "The final charge depends on the billable units of the finished request (megapixels)"
}
```

`unit` is what the price is set for, `price_per_unit` is the price of one unit in credits (the markup is already included). Models with the units `images`, `megapixels`, `seconds` and `videos` are supported. For the others (for example, payment by compute time) submitting answers `400 unsupported_model`. A model that fal does not have is `404 model_not_found`.

## Submitting a task

```bash
curl -X POST "https://api.6io.io/native/fal/queue/fal-ai/flux/schnell" \
  -H "Authorization: Bearer sixio_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"prompt": "a red circle on white background", "image_size": {"width": 1024, "height": 1024}}'
```

The answer:

```json
{
  "request_id": "req_8fK2xQ1mZpVwT9sJdL4nAg",
  "status": "IN_QUEUE",
  "status_url": "https://api.6io.io/native/fal/requests/req_8fK2xQ1mZpVwT9sJdL4nAg/status",
  "response_url": "https://api.6io.io/native/fal/requests/req_8fK2xQ1mZpVwT9sJdL4nAg",
  "cancel_url": "https://api.6io.io/native/fal/requests/req_8fK2xQ1mZpVwT9sJdL4nAg/cancel"
}
```

`request_id` and the links are ours, not fal's: the task belongs to your account, and nobody else's can be opened. Of the query string parameters only `fal_webhook` is accepted, the address for a [notification](https://api.6io.io/md/en/webhooks.md) about the end of the task; the others are not supported. The `Idempotency-Key` header works as in chat: see [Retries and failures](https://api.6io.io/md/en/retries.md).

## A notification instead of polling

Add `?fal_webhook=<address>` (the address encoded) to the submit address, and we send the outcome to it when fal ends the task. The body of the notification is built like a fal webhook (`request_id`, `status` `OK` or `ERROR`, `payload`), but it is signed with our secret by Standard Webhooks, and the file links are ours. Details, signature verification and retries are on the [Webhooks](https://api.6io.io/md/en/webhooks.md) page.

## Status, result, cancel

- `GET status_url`: `IN_QUEUE`, `IN_PROGRESS` or `COMPLETED` (fal's words here, as in its SDK; in Sixio and jobs the states are `queued`, `running`, `succeeded`, `failed`). If fal ended the task with an error, the answer has an `error` field.
- `GET response_url`: the model's result in the fal format. While the task is not ready, the answer is as at fal (`400`, "still in progress").
- `PUT cancel_url`: cancel. `200` means the task was taken off the line and will not run, and the money is returned. `202` means the signal was sent to a running task: it may have reached the end, and then it is paid for.

**File links in the result lead to our server** and are valid for a limited time (14 days by default). Download what you need to keep longer.

## Money

1. Before submitting, an estimate is reserved: the price of a unit × the expected number of units (the number of images, the size in megapixels rounded up, the video length, 5 seconds by default).
2. The final amount is charged by fal's data on the units actually billed. They appear a few minutes after completion. Until then the request is in the state `billing_pending`; this is normal, and you get the result at once.
3. A task that fal ended with an error is not paid for: the reserve is returned after a short time.

Only a limited number of tasks can run at the same time. Images, video and audio have their own limit, separate from the chat limit. Details are in [Errors and limits](https://api.6io.io/md/en/errors-and-limits.md).
