Jobs API
Create and manage long-running workflow jobs. Jobs are used for complex operations like video generation that take several minutes to complete.
Endpoints
POST
/api/v1/jobsCreate a new job
GET
/api/v1/jobsList your jobs
GET
/api/v1/jobs/{id}Get job status
DELETE
/api/v1/jobs/{id}Cancel a job
Create a Job
POST
/api/v1/jobsRequest Body
| Name | Type | Description |
|---|---|---|
workflowrequired | string | Workflow slug — canonical names (generate_video, generate_image, lipsync_video, etc.) or DB workflows (house-timelapse) |
input | object | Workflow-specific input parameters (prompt, model, imageUrl, etc.) |
webhookUrl | string | URL to receive completion notification |
Example Request
curl -X POST https://vydra.ai/api/v1/jobs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflow": "generate_video",
"input": {
"prompt": "Aerial drone shot of Manhattan at golden hour",
"model": "veo3"
}
}'Response (201 Created)json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "running",
"workflow": "house-timelapse",
"creditsCharged": 150,
"createdAt": "2026-01-26T12:00:00.000Z",
"_links": {
"self": "https://vydra.ai/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000",
"status": "https://vydra.ai/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000"
}
}List Jobs
GET
/api/v1/jobsQuery Parameters
| Name | Type | Description |
|---|---|---|
limit | numberDefault: 20 | Max results (1-100) |
offset | numberDefault: 0 | Pagination offset |
status | string | Filter by status: pending, running, completed, failed |
Examplebash
curl "https://vydra.ai/api/v1/jobs?limit=10&status=completed" \
-H "Authorization: Bearer YOUR_API_KEY"Responsejson
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"progress": 100,
"workflowSlug": "house-timelapse",
"statusMessage": "Video generated successfully",
"creditsCharged": 150,
"createdAt": "2026-01-26T12:00:00.000Z",
"completedAt": "2026-01-26T12:15:00.000Z",
"output": {
"videoUrl": "https://pub-xxx.r2.dev/videos/output.mp4"
}
}
],
"pagination": {
"limit": 10,
"offset": 0,
"count": 1
}
}Get Job Status
GET
/api/v1/jobs/{id}Examplebash
curl https://vydra.ai/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY"Response States
Pending
{
"id": "...",
"status": "pending",
"progress": 0,
"statusMessage": "Waiting to start..."
}Running
{
"id": "...",
"status": "running",
"progress": 45,
"statusMessage": "Generating video 2 of 3..."
}Completed
{
"id": "...",
"status": "completed",
"progress": 100,
"output": {
"videoUrl": "https://pub-xxx.r2.dev/videos/output.mp4",
"thumbnailUrl": "https://pub-xxx.r2.dev/videos/thumbnail.jpg"
}
}Failed
{
"id": "...",
"status": "failed",
"error": {
"message": "Processing error",
"code": "PROCESSING_ERROR"
},
"creditsRefunded": 150,
"refundStatus": "completed"
}Cancel a Job
DELETE
/api/v1/jobs/{id}Examplebash
curl -X DELETE https://vydra.ai/api/v1/jobs/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY"Responsejson
{
"success": true,
"message": "Job cancelled",
"refund": {
"applied": true,
"creditsRefunded": 150
}
}Auto-Refund on Cancel
When you cancel a job, any charged credits are automatically refunded.
Webhooks
Instead of polling for status, provide a webhookUrl to receive notifications when jobs complete.
Webhook Payload (Success)
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"workflow": "house-timelapse",
"output": {
"videoUrl": "https://pub-xxx.r2.dev/videos/output.mp4"
},
"completedAt": "2026-01-26T12:15:00.000Z"
}Webhook Payload (Failure)
{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "failed",
"workflow": "renovation-timelapse",
"error": {
"message": "Processing failed",
"code": "PROCESSING_ERROR"
},
"refund": {
"applied": true,
"creditsRefunded": 50
},
"completedAt": "2026-01-26T12:15:00.000Z"
}Job Statuses
| Status | Description | Final? |
|---|---|---|
pending | Job created, waiting to start | No |
running | Job is actively processing | No |
completed | Job finished successfully | Yes |
failed | Job encountered an error | Yes |
cancelled | Job was cancelled by user | Yes |
Polling Example
If you can't use webhooks, poll for status:
Polling Implementationjavascript
async function waitForJob(jobId, apiKey, maxWaitMs = 30 * 60 * 1000) {
const startTime = Date.now();
const pollInterval = 5000; // 5 seconds
while (Date.now() - startTime < maxWaitMs) {
const response = await fetch(`https://vydra.ai/api/v1/jobs/${jobId}`, {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const job = await response.json();
console.log(`Status: ${job.status}, Progress: ${job.progress}%`);
if (job.status === 'completed') {
return job.output;
}
if (job.status === 'failed') {
throw new Error(job.error?.message || 'Job failed');
}
// Wait before next poll
await new Promise(resolve => setTimeout(resolve, pollInterval));
}
throw new Error('Job timed out');
}
// Usage
const output = await waitForJob('job-id', 'YOUR_API_KEY');
console.log('Video URL:', output.videoUrl);Rate Limits
Polling counts against your rate limits. Use webhooks when possible, or poll no more than once every 5 seconds.