Developer Reference

API Documentation

Two endpoints. One POST to start — one GET to poll status. The pipeline runs asynchronously; your video is ready in ~3–5 minutes.

BASE URL https://www.forsa-ai-api.midadworld.com/api/v1

🚀 Quick Start

1 — Set up environment

# Install PHP dependencies composer install # Copy and configure environment cp .env.example .env php artisan key:generate php artisan migrate # Start video queue worker php artisan queue:work --queue=videos --timeout=600 # Start dev server php artisan serve

2 — Required .env keys

DB_CONNECTION=mysql DB_DATABASE=forsa_videos QUEUE_CONNECTION=redis SEEDREAM_API_KEY=sk-seed-... SEEDREAM_API_URL=https://api.seedream.io/v1 OPENAI_API_KEY=sk-proj-... ELEVENLABS_API_KEY=sk-el-... ELEVENLABS_VOICE_ID=your_voice_id OMNIHUMAN_API_KEY=... OMNIHUMAN_API_URL=https://api.omnihuman.io/v1 SEEDANCE_API_KEY=... SEEDANCE_API_URL=https://api.seedance.io/v1

Authentication

The API currently uses no authentication — designed to run as an internal service behind your own gateway. Add Authorization: Bearer middleware in routes/api.php before public exposure.

Do not expose this API publicly without authentication and rate limiting.

POST Generate Video

POST /api/v1/generate-car-video multipart/form-data

Submits a new video generation job. Returns a job_id UUID — use it to poll the status endpoint.

Request Fields

FieldTypeRequiredDescription
images[] file[] ● Required 3–4 car photos. JPEG/PNG, max 10 MB each.
car_brand string ● Required Car manufacturer. e.g. Toyota
car_model string ● Required Car model. e.g. Land Cruiser
car_year integer ○ Optional Model year. Defaults to current year.
presenter_gender enum ○ Optional male or female. Default: male
language enum ○ Optional ar (Arabic) or en (English). Default: ar

Response — 202 Accepted

{ "success": true, "job_id": "550e8400-e29b-41d4-a716-446655440000", "message": "Video generation started", "status_url": "/api/v1/generate-car-video/550e8400.../status" }

GET Check Status

GET /api/v1/generate-car-video/{jobId}/status Poll every 10–15s

Returns the current state of the generation job. Poll until status is completed or failed.

Status Values

pending — Job queued
processing — Pipeline running
completed — video_url ready
failed — Check error_message

Response — Completed

{ "success": true, "status": "completed", "current_step": 9, "video_url": "/storage/videos/550e8400.../final.mp4", "created_at": "2024-01-15T10:30:00Z" }

Response Schemas

processing
{ "status":"processing", "current_step":4, "video_url":null }
failed
{ "success":false, "status":"failed", "error_message":"OmniHuman: timeout" }
422
{ "message":"Validation failed", "errors":{"images":["Min 3 images required"]} }

Code Examples

Submit a job via cURL
# POST: Submit job curl -X POST https://www.forsa-ai-api.midadworld.com/api/v1/generate-car-video \ -H "Accept: application/json" \ -F "images[]=@/path/car1.jpg" \ -F "images[]=@/path/car2.jpg" \ -F "images[]=@/path/car3.jpg" \ -F "car_brand=Toyota" \ -F "car_model=Land Cruiser" \ -F "car_year=2024" \ -F "presenter_gender=male" \ -F "language=ar" # GET: Poll status curl https://www.forsa-ai-api.midadworld.com/api/v1/generate-car-video/{JOB_ID}/status \ -H "Accept: application/json"
PHP — Guzzle HTTP client
use GuzzleHttp\Client; $client = new Client(['base_uri' => 'https://www.forsa-ai-api.midadworld.com']); $response = $client->post('/api/v1/generate-car-video', [ 'multipart' => [ ['name' => 'images[]', 'contents' => fopen('/path/car1.jpg', 'r'), 'filename' => 'car1.jpg'], ['name' => 'images[]', 'contents' => fopen('/path/car2.jpg', 'r'), 'filename' => 'car2.jpg'], ['name' => 'images[]', 'contents' => fopen('/path/car3.jpg', 'r'), 'filename' => 'car3.jpg'], ['name' => 'car_brand', 'contents' => 'Toyota'], ['name' => 'car_model', 'contents' => 'Land Cruiser'], ['name' => 'language', 'contents' => 'ar'], ], ]); $jobId = json_decode($response->getBody(), true)['job_id']; do { sleep(10); $res = $client->get("/api/v1/generate-car-video/{$jobId}/status"); $body = json_decode($res->getBody(), true); } while (in_array($body['status'], ['pending', 'processing'])); echo $body['video_url'];
JavaScript — Fetch API
const fd = new FormData(); files.forEach(f => fd.append('images[]', f)); fd.append('car_brand', 'Toyota'); fd.append('car_model', 'Land Cruiser'); fd.append('language', 'ar'); const { job_id } = await (await fetch('https://www.forsa-ai-api.midadworld.com/api/v1/generate-car-video', { method: 'POST', body: fd })).json(); while (true) { await new Promise(r => setTimeout(r, 10000)); const s = await (await fetch(`https://www.forsa-ai-api.midadworld.com/api/v1/generate-car-video/${job_id}/status`)).json(); if (s.status === 'completed') { console.log(s.video_url); break; } if (s.status === 'failed') throw new Error(s.error_message); }

HTTP Status Codes

CodeMeaningWhen It Occurs
202 Accepted Job successfully queued.
200 OK Status poll returned.
404 Not Found job_id does not exist.
422 Unprocessable Entity Validation failed — check errors.
500 Internal Server Error Unexpected server failure.