Text to video api
A prompt alone is a text clip. An image animates that photo for one clip. Poll /api/videos/{id}/ with the same key until the clip is READY.
$1 for a 5-second 540x960 clip (12 credits). The ultra tier is 720x1280.
Auth
Create a key at /users/api-keys/. The plaintext is shown once and starts with sk_live_.
| Header | Authorization: Bearer then the key |
|---|---|
| Also accepted | X-API-Key with the same key |
| Missing key | 401 {"detail": "Authentication credentials were not provided."} on a read. Generate allows an account-less caller only while machine payments are on, and then answers 402. |
| Unknown or inactive key | 401 {"detail": "Invalid API key"} |
POST /api/videos/generate/
JSON body. A prompt creates a text clip. Set image to animate a photo. The response is 201 as soon as the job is queued.
| prompt | Required string, at most 1000 characters. |
|---|---|
| duration | Integer. Default 5, minimum 5, maximum 60. An image replaces it with 5. When the account has an API quota, a non-staff key cannot ask for more than that quota's max_video_duration. The message is Duration cannot exceed {max_video_duration} seconds for your subscription plan. |
| resolution | Tier key. Accepted values: 540x960, 720x1280. Default 540x960. An image replaces it with 540x960. Any other tier is rejected. |
| image | Optional. An https URL or a photo file as base64. http is rejected with Image must be an https URL or a photo file. A file that is not a photo is rejected with That file is not a photo. A stored photo is at most 2048 pixels on the long edge and 8000000 bytes. An https URL is fetched later, up to 41943040 bytes. |
| negative_prompt | Optional string, at most 500 characters. Blank and null are accepted. |
| seed | Optional integer. Null is accepted. |
curl -X POST https://sisif.ai/api/videos/generate/ \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"prompt": "A lighthouse at dusk", "duration": 5, "resolution": "540x960"}'
201 body
| id | Integer video id. |
|---|---|
| status | The row's status after the job is queued, which is PROCESSING. |
| prompt | The prompt that was stored. |
| duration | Seconds stored. An image request stores 5. |
| resolution | Tier key stored. An image request stores 540x960. |
| estimated_completion | A timestamp 5 minutes after the response is built. |
| credits_used | Credits calculated for that duration and tier before the job starts. |
| created_at | When the row was created. |
| api_key | Present only when a payment with no account minted a key. Shown once. That key is how the caller polls. |
GET /api/videos/{id}/
Poll with the same Bearer key. The clip must belong to that key's account. Repeat the GET until status is READY, ERROR, REFUNDED.
Statuses: PENDING, QUEUED, RETRYING, PROCESSING, READY, ERROR, REFUNDED. Still running: PENDING, QUEUED, RETRYING, PROCESSING.
| id | Integer. |
|---|---|
| prompt | String. |
| status | One of the statuses above. |
| video_url | File URL. Empty until the file is stored. |
| poster_url | Poster URL. Empty when there is no poster. |
| duration | Seconds. |
| resolution | Tier key, not a measured pixel size. |
| output_width | Stored file width, or null before it is known. |
| output_height | Stored file height, or null before it is known. |
| featured | Boolean. New API clips are not featured. |
| created_at | Timestamp. |
| updated_at | Timestamp. |
GET /api/videos/{id}/status/
The same account scope. Always returns id, status, progress, created_at, and updated_at. video_url is included when status is READY and the file URL is set. poster_url is included when a poster is set. error_message is included when status is ERROR, using the stored message or Generation failed.
| PENDING | progress 10 |
|---|---|
| PROCESSING | progress 50 |
| READY | progress 100 |
| ERROR | progress 0 |
| Any other status | progress 0 |
Watch
The watch page is /app/watch/{id}/. It answers only when status is READY and the clip is featured, public, or the viewer is signed in as the owner. An API clip starts private and unfeatured, so the owner opens that page while signed in. The file itself is video_url on the detail response.
Errors
| 400 | {"error": "validation_error", "message": "Invalid request data", "details": {}} and details is the field errors. |
|---|---|
| 401 | {"detail": "..."}. Invalid API key, or Rate limit exceeded (per minute), Rate limit exceeded (per hour), or Rate limit exceeded (per day). |
| 402 | insufficient_credits when the account is short: message Insufficient credits. Need {cost}, have {balance}, details required_credits and available_credits. payment_required when there is no account: message This clip costs {cost} credits. Pay the challenge in WWW-Authenticate., details required_credits and usd_amount. payment_failed when a credential is refused. A replayed payment says payment already redeemed. |
| 404 | {"detail": "Not found."} for a missing id or another account's clip. |
| 429 | An unkeyed generate call past the anonymous limit. The detail is Request was throttled. Expected available in {wait} second. when the wait is 1, and Request was throttled. Expected available in {wait} seconds. otherwise. The response carries Retry-After. A keyed caller who is over the key's own limit gets 401, not 429. |
| 502 | {"error": "generation_failed", "message": "Video generation could not be started. Please try again."} Credits are not taken when the job never queues. A later failure returns the credits. |
Limits and price
$1 buys 12 credits: 5 seconds at 540x960. Credits for a text clip are the duration times the tier coefficient, with the fraction dropped. An image is priced as that same clip, because duration and resolution are replaced.
| 540x960 | 2.5 credits per second |
|---|---|
| 720x1280 | 6.0 credits per second |
| Per key | 10 per minute, 100 per hour, 1000 per day. Those are the defaults on a new key. |
| No key | 30/hour on generate, per address. |
| Prompt | 1000 characters. Negative prompt 500. |
| Duration | 5 to 60 seconds, unless a quota sets a lower maximum. |