Developer API: Generate Creator UGC Videos from Your Own App
Connect your product to ppl.studio and produce creator videos programmatically—send a script, get back a finished MP4 URL. No browser, no manual steps.
ppl.studio's Creator Video pipeline runs behind a small HTTP API. Your app sends a script and a creator (a UGC persona); ppl.studio generates the frames, animates them with Veo, assembles the cut, and hands you a hosted MP4. Everything you make is owned by your account and shows up in your gallery.
What you can integrate today
One rule explains the whole surface: a per-user API key authorizes the /api/v1/* endpoints and resolves to your account. Any persona or product you reference must be owned by that same account.
- Generate a creator video (script → MP4) — available via API
- Poll or webhook a video job — available via API
- Creators (personas) — create them in the dashboard (owned by your account), then reference by slug
- Photo packs & product management — in-app today; API access is on the roadmap (see the end)
How it works: the async job model
A creator video isn't a single render. Your N-segment script becomes N first-frames, N Veo clips (90–180s each), and one assembly pass—about 8–10 minutes total. No HTTP request stays open that long, so the API is a job: you enqueue and get a jobId immediately, then collect the finished URL by polling or via a webhook.
A standalone worker drains the queue, polls Veo to completion, and assembles the cut. Jobs move through queued → rendering → assembling → done (or failed, with a reason).
Step 1 — Create your creator
A persona supplies the face and voice of every video and must be owned by your account. Create it in the ppl.studio dashboard—see Create Your First AI Expert—and note its slug (e.g. alex-reed). You can have many. Reference the slug on every video request.
Step 2 — Mint an API key
Open Account → API keys, create a key, and copy it immediately—the raw key (ppl_live_…) is shown once; only its hash is stored. Send it on every request as a header, either form works:
x-api-key: ppl_live_xxxxxxxxxxxxxxxxxxxx
# or
Authorization: Bearer ppl_live_xxxxxxxxxxxxxxxxxxxxStep 3 — Enqueue a video
POST /api/v1/mascot-videos with your key, a persona slug, a format, and one script segment per beat:
POST /api/v1/mascot-videos
x-api-key: ppl_live_xxxxxxxxxxxxxxxxxxxx
content-type: application/json
{
"personaSlug": "alex-reed",
"format": "full-viral",
"script": { "segments": [
{ "role": "hook", "spokenLine": "You're doing this wrong", "onScreenText": "STOP" },
{ "role": "broll", "brollPrompt": "close-up of the product on a marble counter" },
{ "role": "body", "spokenLine": "Here's the 3-second fix", "onScreenText": "The fix" },
{ "role": "cta", "spokenLine": "Tap the link to try it", "onScreenText": "Link below" }
]},
"callbackUrl": "https://your-app.com/webhooks/ppl"
}
// → 202 { "ok": true, "data": { "jobId", "status": "queued", "statusUrl" } }Formats & segment counts(enforced—send exactly this many, in order):
wisdom-bomb— 1: hookhook-broll-payoff— 3: hook, broll, bodyfull-viral— 4: hook, broll, body, ctastory-pov— 4: hook, body, body, cta
Talking roles use spokenLine (what the creator says) and optional onScreenText (caption). broll segments use brollPrompt (a product scene with no person). callbackUrl is optional and must be https.
Step 4 — Collect the result
Webhook (if you sent callbackUrl) — ppl.studio POSTs on completion:
{ "event": "mascot_video.done", "jobId": "…", "status": "done", "videoUrl": "https://…/combined.mp4" }
{ "event": "mascot_video.failed", "jobId": "…", "status": "failed", "error": "…" }Or poll GET /api/v1/mascot-videos/{jobId} every ~15–30s until status is done or failed. The webhook is best-effort (10s timeout, no retries yet), so treat polling as the source of truth and the webhook as a latency optimization.
Drop-in client (Node)
Enqueue, then await the URL:
const BASE = "https://people.voiceherald.com";
const KEY = process.env.PPL_API_KEY; // ppl_live_…
async function createCreatorVideo({ personaSlug, format, segments, callbackUrl }) {
const res = await fetch(`${BASE}/api/v1/mascot-videos`, {
method: "POST",
headers: { "content-type": "application/json", "x-api-key": KEY },
body: JSON.stringify({ personaSlug, format, script: { segments }, callbackUrl }),
});
const body = await res.json();
if (!res.ok || !body.ok) throw new Error(body.error ?? `enqueue failed (${res.status})`);
return body.data; // { jobId, status, statusUrl }
}
async function waitForVideo(statusUrl, { intervalMs = 20000 } = {}) {
for (;;) {
await new Promise((s) => setTimeout(s, intervalMs));
const r = await fetch(statusUrl, { headers: { "x-api-key": KEY } });
const { data } = await r.json();
if (data.status === "done") return data.videoUrl;
if (data.status === "failed") throw new Error(data.error);
}
}
// Usage
const job = await createCreatorVideo({
personaSlug: "alex-reed",
format: "wisdom-bomb",
segments: [{ role: "hook", spokenLine: "This one tip changed everything", onScreenText: "WATCH" }],
});
const url = await waitForVideo(job.statusUrl);
console.log("video ready:", url);And a minimal webhook receiver:
app.post("/webhooks/ppl", express.json(), (req, res) => {
const { event, jobId, videoUrl, error } = req.body;
if (event === "mascot_video.done") saveVideo(jobId, videoUrl);
if (event === "mascot_video.failed") markFailed(jobId, error);
res.sendStatus(200); // ack fast
});Conventions & errors
Every /api/v1/* response is one of:
{ "ok": true, "data": { … } }
{ "ok": false, "error": "human-readable message" }400— bad format, wrong segment count, or non-https callback401— missing, invalid, or revoked key404— persona not owned by your account, or job not found500— server error (safe to retry the POST)
Good to know
- Each video costs N frame generations + N Veo renders + one assembly. A 1-segment clip is ready in ~75 seconds; a 4-segment video is ~8–10 minutes.
- The v1 POST doesn't honor an
Idempotency-Keyyet—dedupe retries on your side. - Webhooks have no signature or retry yet—verify via polling and allowlist the sender on your receiver.
- Talking-segment frames currently use a generic UGC-selfie look; richer art direction is a planned addition.
What's next?
Build the pieces around the API, and watch this space for broader programmatic access:
- Create Your First AI Expert — build the persona your videos use
- Animate: Talking-Head Videos — the same pipeline, in the app
- Roadmap: photo packs, product management, and brief generation over the same per-user key (today they're in-app only).
Start building
Create a creator, mint an API key, and ship your first programmatic video in an afternoon.
Get your API key10 free photos · no credit card required
Founder of ppl.studio. Building AI tools for product marketing teams who need visual content at scale without the production overhead.