Agency Plan

API Documentation

Programmatic access to FaceDub video generation. Create, monitor, and retrieve AI-generated UGC videos via REST API.

Authentication

API access requires an Agency plan. Generate API keys from your Dashboard under the API Keys tab.

All API keys start with fdb_ and are shown only once at creation. Store them securely.

Include your API key in the Authorization header:

Header
Authorization: Bearer fdb_your_api_key_here

Base URL

https://api.facedub.io

All endpoints are relative to this base URL.

Endpoints

POST
/jobs

Create a new video generation job

Request Body (multipart/form-data)

FieldTypeDescription
character_photofilePhoto of the character (JPG, PNG, WebP)
reference_videofileReference video with motion to replicate
durationintVideo duration in seconds (1-30, default 5)

Response

200 OK
{
  "job_id": "abc123def456",
  "status": "queued",
  "credits_charged": 2,
  "is_overage": false
}
GET
/jobs

List your recent jobs (up to 50)

200 OK
[
  {
    "id": "abc123def456",
    "status": "completed",
    "stage": "done",
    "output_url": "https://cdn.facedub.io/...",
    "created_at": 1709337600,
    "error": null,
    "duration_seconds": 10,
    "credits_charged": 2
  }
]
GET
/jobs/{job_id}

Get status of a specific job

200 OK
{
  "id": "abc123def456",
  "status": "processing",
  "stage": "generating_views",
  "output_url": null,
  "created_at": 1709337600,
  "error": null,
  "duration_seconds": 10,
  "credits_charged": 2
}
GET
/jobs/{job_id}/stream?token=YOUR_JWT

SSE stream of real-time job status updates

Note: SSE streaming requires a JWT token (not API key). Pass it as a token query parameter since EventSource cannot set headers.

GET
/usage

Get your current credit usage

200 OK
{
  "plan": "agency",
  "credits_used": 42,
  "credits_limit": 150,
  "bonus_credits": 0,
  "credits_remaining": 108
}
POST
/api-keys

Create a new API key (max 5 active)

Request Body (JSON)
{
  "name": "Production Key"
}
200 OK
{
  "id": "key_abc123",
  "name": "Production Key",
  "key": "fdb_a1b2c3d4e5f6...",
  "prefix": "fdb_a1b2c3d4",
  "created_at": 1709337600
}

The full key is returned only once at creation. Store it securely.

GET
/api-keys

List your API keys (prefix only)

DELETE
/api-keys/{key_id}

Revoke an API key

Job Statuses

queued

Job is waiting in the processing queue

processing

AI pipeline is actively generating the video

completed

Video is ready — output_url is populated

failed

Generation failed — check the error field

Rate Limits

Requests are rate-limited per user on a sliding 1-minute window. Exceeding the limit returns 429 Too Many Requests with a Retry-After header.

EndpointLimit
POST /jobs10/min
GET /jobs/*60/min
All other endpoints120/min

Concurrency

API access allows up to 2 concurrent jobs per user. Submitting a 3rd job while 2 are still processing returns 429. Wait for a job to complete before submitting more.

Code Examples

cURL

Create a job
curl -X POST https://api.facedub.io/jobs \
  -H "Authorization: Bearer fdb_your_key_here" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "duration=10"

Python

python
import requests
import time

API_KEY = "fdb_your_key_here"
BASE = "https://api.facedub.io"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Create job
with open("photo.jpg", "rb") as photo, open("video.mp4", "rb") as video:
    res = requests.post(
        f"{BASE}/jobs",
        headers=headers,
        files={
            "character_photo": photo,
            "reference_video": video,
        },
        data={"duration": 10},
    )

job = res.json()
print(f"Job created: {job['job_id']}")

# Poll for completion
while True:
    status = requests.get(
        f"{BASE}/jobs/{job['job_id']}",
        headers=headers,
    ).json()
    print(f"Status: {status['status']} — {status['stage']}")
    if status["status"] in ("completed", "failed"):
        break
    time.sleep(5)

if status["status"] == "completed":
    print(f"Download: {status['output_url']}")

Node.js

javascript
const fs = require("fs");

const API_KEY = "fdb_your_key_here";
const BASE = "https://api.facedub.io";

async function createVideo() {
  const form = new FormData();
  form.append("character_photo", fs.createReadStream("photo.jpg"));
  form.append("reference_video", fs.createReadStream("video.mp4"));
  form.append("duration", "10");

  const res = await fetch(`${BASE}/jobs`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: form,
  });
  const job = await res.json();
  console.log("Job created:", job.job_id);

  // Poll for completion
  while (true) {
    const status = await fetch(`${BASE}/jobs/${job.job_id}`, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    }).then((r) => r.json());

    console.log(`Status: ${status.status} — ${status.stage}`);
    if (["completed", "failed"].includes(status.status)) {
      if (status.status === "completed") {
        console.log("Download:", status.output_url);
      }
      break;
    }
    await new Promise((r) => setTimeout(r, 5000));
  }
}

createVideo();

Error Codes

CodeMeaning
400Bad request — invalid parameters
401Unauthorized — missing or invalid API key
403Forbidden — not on Agency plan, or account suspended
404Not found — job doesn't exist or isn't yours
429Too many requests — rate or concurrency limit exceeded
500Internal server error — try again or contact support

Need Help?

Agency plan includes priority support. Reach out at [email protected]