Install
openclaw skills install fal-ai-apifal.ai API integration with managed API key authentication. Run AI models for image generation, video generation, audio processing, and more. Use this skill when users want to generate images (Flux, SDXL), create videos (Minimax), upscale images, transcribe audio, or run other AI models on fal.ai. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install fal-ai-apiAccess the fal.ai queue API with managed API key authentication. Run 1000+ AI models including image generation (Flux, SDXL), video generation (Minimax), image upscaling, text-to-speech, and more.
# Generate an image with Flux Schnell
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"prompt": "a tiny cute cat",
"image_size": "square_hd",
"num_images": 1
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/fal-ai/fal-ai/flux/schnell', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://gateway.maton.ai/fal-ai/{native-api-path}
The gateway proxies requests to queue.fal.run. For model inference, paths follow the pattern:
/fal-ai/fal-ai/{model-id}
/fal-ai/fal-ai/{model-id}/requests/{request_id}/status
/fal-ai/fal-ai/{model-id}/requests/{request_id}
/fal-ai/fal-ai/{model-id}/requests/{request_id}/cancel
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your fal.ai API key connections at https://ctrl.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=fal-ai&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'fal-ai'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "7355bd0b-8aaf-4c58-9122-a1e3d454414d",
"status": "PENDING",
"url": "https://connect.maton.ai/?session_token=...",
"app": "fal-ai",
"method": "API_KEY"
}
}
Open the returned url in a browser to enter your fal.ai API key.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
The fal.ai queue API provides asynchronous model inference with status polling.
Submit a request to run a model. Returns immediately with a request ID.
POST /fal-ai/fal-ai/{model-id}
Content-Type: application/json
{
"prompt": "model-specific parameters",
...
}
Response:
{
"status": "IN_QUEUE",
"request_id": "3229f185-a99a-48c0-a292-e25bf9baaeba",
"response_url": "https://queue.fal.run/fal-ai/flux/requests/3229f185-a99a-48c0-a292-e25bf9baaeba",
"status_url": "https://queue.fal.run/fal-ai/flux/requests/3229f185-a99a-48c0-a292-e25bf9baaeba/status",
"cancel_url": "https://queue.fal.run/fal-ai/flux/requests/3229f185-a99a-48c0-a292-e25bf9baaeba/cancel",
"queue_position": 0
}
Poll for request status until completion.
GET /fal-ai/fal-ai/{model-id}/requests/{request_id}/status
Response (IN_PROGRESS):
{
"status": "IN_PROGRESS",
"request_id": "3229f185-a99a-48c0-a292-e25bf9baaeba"
}
Response (COMPLETED):
{
"status": "COMPLETED",
"request_id": "3229f185-a99a-48c0-a292-e25bf9baaeba",
"metrics": {
"inference_time": 0.3334658145904541
}
}
Retrieve the completed result.
GET /fal-ai/fal-ai/{model-id}/requests/{request_id}
Response (image generation):
{
"images": [
{
"url": "https://v3b.fal.media/files/...",
"width": 1024,
"height": 1024,
"content_type": "image/jpeg"
}
],
"timings": {
"inference": 0.1587670766748488
},
"seed": 761506470,
"prompt": "a tiny cute cat"
}
Cancel a queued or in-progress request.
PUT /fal-ai/fal-ai/{model-id}/requests/{request_id}/cancel
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"prompt": "a serene mountain landscape at sunset",
"image_size": "landscape_16_9",
"num_images": 1,
"num_inference_steps": 4
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/fal-ai/fal-ai/flux/schnell', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Parameters:
prompt (required): Text description of the imageimage_size: square_hd, square, portrait_4_3, portrait_16_9, landscape_4_3, landscape_16_9num_images: Number of images to generate (default: 1)num_inference_steps: Number of steps (default: 4)seed: Random seed for reproducibilitypython <<'EOF'
import urllib.request, os, json
data = json.dumps({
"prompt": "a futuristic city skyline at night",
"negative_prompt": "blurry, low quality",
"image_size": "landscape_16_9",
"num_images": 1
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/fal-ai/fal-ai/fast-sdxl', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Parameters:
prompt (required): Text descriptionnegative_prompt: What to avoid in the imageimage_size: Output dimensionsnum_images: Number of imagesguidance_scale: CFG scale (default: 7.5)num_inference_steps: Number of stepspython <<'EOF'
import urllib.request, os, json
data = json.dumps({
"image_url": "https://example.com/image.jpg",
"scale": 2
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/fal-ai/fal-ai/clarity-upscaler', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Parameters:
image_url (required): URL of the image to upscalescale: Upscale factor (2, 4)python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"prompt": "A cat playing with a ball in slow motion"
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/fal-ai/fal-ai/minimax/video-01', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"gen_text": "Hello world, this is a test of fal ai text to speech."
}).encode()
req = urllib.request.Request('https://gateway.maton.ai/fal-ai/fal-ai/f5-tts', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
| Status | Description |
|---|---|
IN_QUEUE | Request received, waiting for runner |
IN_PROGRESS | Model is processing the request |
COMPLETED | Processing finished, result available |
FAILED | Processing failed (check error details) |
| Header | Description |
|---|---|
X-Fal-Request-Timeout | Server-side deadline in seconds |
X-Fal-Runner-Hint | Session affinity for routing |
X-Fal-Queue-Priority | normal (default) or low |
X-Fal-No-Retry | Disable automatic retries |
python <<'EOF'
import urllib.request, os, json, time
api_key = os.environ["MATON_API_KEY"]
base_url = "https://gateway.maton.ai/fal-ai"
# 1. Submit request
data = json.dumps({
"prompt": "a beautiful sunset over the ocean",
"image_size": "landscape_16_9",
"num_images": 1
}).encode()
req = urllib.request.Request(f'{base_url}/fal-ai/flux/schnell', data=data, method='POST')
req.add_header('Authorization', f'Bearer {api_key}')
req.add_header('Content-Type', 'application/json')
submit_response = json.load(urllib.request.urlopen(req))
request_id = submit_response['request_id']
print(f"Submitted: {request_id}")
# 2. Poll for completion
while True:
req = urllib.request.Request(f'{base_url}/fal-ai/flux/requests/{request_id}/status')
req.add_header('Authorization', f'Bearer {api_key}')
status_response = json.load(urllib.request.urlopen(req))
print(f"Status: {status_response['status']}")
if status_response['status'] == 'COMPLETED':
break
elif status_response['status'] == 'FAILED':
print("Request failed")
exit(1)
time.sleep(1)
# 3. Get result
req = urllib.request.Request(f'{base_url}/fal-ai/flux/requests/{request_id}')
req.add_header('Authorization', f'Bearer {api_key}')
result = json.load(urllib.request.urlopen(req))
print(f"Image URL: {result['images'][0]['url']}")
EOF
const submitRequest = async () => {
// Submit
const submitRes = await fetch('https://gateway.maton.ai/fal-ai/fal-ai/flux/schnell', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
},
body: JSON.stringify({
prompt: 'a tiny cute cat',
image_size: 'square_hd',
num_images: 1
})
});
const { request_id } = await submitRes.json();
// Poll
let status = 'IN_QUEUE';
while (status !== 'COMPLETED') {
await new Promise(r => setTimeout(r, 1000));
const statusRes = await fetch(
`https://gateway.maton.ai/fal-ai/fal-ai/flux/requests/${request_id}/status`,
{ headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } }
);
status = (await statusRes.json()).status;
}
// Get result
const resultRes = await fetch(
`https://gateway.maton.ai/fal-ai/fal-ai/flux/requests/${request_id}`,
{ headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } }
);
return await resultRes.json();
};
import os
import time
import requests
api_key = os.environ["MATON_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}"}
# Submit
response = requests.post(
"https://gateway.maton.ai/fal-ai/fal-ai/flux/schnell",
headers=headers,
json={"prompt": "a tiny cute cat", "image_size": "square_hd", "num_images": 1}
)
request_id = response.json()["request_id"]
# Poll
while True:
status = requests.get(
f"https://gateway.maton.ai/fal-ai/fal-ai/flux/requests/{request_id}/status",
headers=headers
).json()["status"]
if status == "COMPLETED":
break
time.sleep(1)
# Get result
result = requests.get(
f"https://gateway.maton.ai/fal-ai/fal-ai/flux/requests/{request_id}",
headers=headers
).json()
print(result["images"][0]["url"])
queue.fal.run for model inference?fal_webhook=URL to submit request)jq, environment variables may not expand correctly. Use Python examples instead.| Status | Meaning |
|---|---|
| 400 | Missing fal-ai connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 422 | Invalid model parameters |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from fal.ai API |
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=fal-ai&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Verify path format: Paths must start with /fal-ai/fal-ai/{model-id}
Check model exists: Some model IDs include organization prefix (e.g., fal-ai/flux/schnell)