Available models
| ID | Provider | Price/sec | Default duration | Max | Audio |
|---|---|---|---|---|---|
google/veo-3.1 | $0.40 | 8s | 8s | ✅ | |
google/veo-3 | $0.20 | 8s | 8s | ❌ | |
fal/veo-3.1 | fal.ai | $0.40 | 8s | 8s | ✅ |
fal/runway-gen-4 | fal.ai | $0.05 | 5s | 10s | ❌ |
fal/luma-ray-2 | fal.ai | $0.20 | 5s | 9s | ❌ |
fal/kling-2 | fal.ai | $0.04 | 5s | 10s | ❌ |
fal/hailuo-02 | fal.ai | $0.04 | 6s | 10s | ❌ |
Usage pattern
Polling is lazy: the job doesn’t advance on its own (Kling/Veo process on their side). But the provider keeps working even if you don’t poll — when you do poll you’ll see the updated state.
Job states
| Status | Meaning |
|---|---|
pending | Job created in our DB, not yet sent to provider |
processing | Provider is rendering |
completed | Done. video_url points to your Supabase Storage |
failed | An error occurred. error describes the cause |
completed (at model price × duration × markup × FX).
If the job fails, you’re not charged.
Storage
Same as images: finished videos upload to your Supabase Storage (generated-videos) with persistent public UUID-based URLs.
Next steps
POST /v1/videos/generations
Submit a new video job.
GET /v1/videos/{id}
Poll the job status.