Turn any website URL into a studio-quality video — programmatically. One POST creates and renders the video; poll one endpoint for the result. Perfect for automations, bulk generation, and video Open Graph previews.
Using an AI assistant?Connect PageToVid to Claude, Cursor, VS Code or Codex and just ask for a video.Create an API key in your account, then send it as a Bearer token. Keep it secret — it spends your credits.
httpAuthorization: Bearer cp_live_xxxxxxxxxxxxxxxx
Base URL: https://pagetovid.com · a rendered video costs 40 credits.
POST /api/v1/videos — returns immediately with an id; rendering runs async.
curlcurl -X POST https://pagetovid.com/api/v1/videos \ -H "Authorization: Bearer $PAGETOVID_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://stripe.com", "goal": "ad", // explainer | ad | demo | tutorial "aspect": "16:9", // 16:9 | 9:16 | 1:1 "language": "en", "targetSeconds": 35, "subtitles": true }'
Response (202):
json{ "id": "cmq…", "status": "analyzing", "statusUrl": "https://pagetovid.com/api/v1/videos/cmq…" }
GET /api/v1/videos/:id — poll until status: "done".
json{ "id": "cmq…", "status": "done", // analyzing | scripting | recording | voicing | rendering | done | error "progress": 100, "videoUrl": "https://pagetovid.com/media/cmq…/video.mp4", "posterUrl": "https://pagetovid.com/media/cmq…/scene-2.png", "subtitleUrl": "https://pagetovid.com/media/cmq…/subtitles.vtt", "durationMs": 41000, "width": 1920, "height": 1080, "og": { "og:video": "…", "og:image": "…", "og:video:type": "video/mp4", … } }
Everything an assistant can do through the MCP is also a REST door, with the same bearer key. A site is identified by its domain.
/api/v1/sites/:domain/plan — the plan for a whole site — the videos it should have, each with a goal, a brief and its shots. POST generates or regenerates it (free)./api/v1/sites/:domain/plan/videos — the set of videos the plan asks for, with the video each idea already became. POST previews what it would make; POST with confirm: true starts them, 40 credits each./api/v1/sites/:domain/shows — the site's shows — recurring videos from an RSS, Atom or JSON feed: the same storyboard every episode, new data every episode. POST creates one; it starts held./api/v1/shows/:id/run — runs a show by hand. Without confirm it previews the episodes for free; confirm: true makes them (40 credits each) and, on a held show, confirms it — the hourly scheduler runs it from then on, within its per-run and per-day caps. PATCH /api/v1/shows/:id pauses, resumes or retunes it.json// POST /api/v1/sites/example.com/shows { "name": "Release notes", "kind": "video", "feed_kind": "rss", "feed_url": "https://example.com/changelog.xml", "cadence": "weekly", "max_episodes_per_run": 1, "max_credits_per_day": 2, "aspect_ratio": "9:16", "language": "en", "goal": "explainer", "target_seconds": 30, "focus_template": "This episode is about {{title}}: {{summary}}. Lead with what is new." } // → 201 { show: { show_id, confirmed: false, ... } } then POST /api/v1/shows/:id/run { "confirm": true }
A show never spends before its owner has seen a run once, never more than max_credits_per_day in a day, and never makes the same feed item twice.
A finished video doubles as a rich og:video preview — so links to your page unfurl as a playable video on social and search. The status response hands you the exact tags in og. Drop them in your page's <head>:
html<meta property="og:image" content="POSTER_URL" /> <meta property="og:video" content="VIDEO_URL" /> <meta property="og:video:secure_url" content="VIDEO_URL" /> <meta property="og:video:type" content="video/mp4" /> <meta property="og:video:width" content="1920" /> <meta property="og:video:height" content="1080" /> <meta name="twitter:card" content="player" />
Generate + wait, in any language.
javascriptconst KEY = process.env.PAGETOVID_API_KEY; const create = await fetch("https://pagetovid.com/api/v1/videos", { method: "POST", headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ url: "https://your-site.com", goal: "ad" }), }).then((r) => r.json()); let v; do { await new Promise((r) => setTimeout(r, 5000)); v = await fetch(create.statusUrl, { headers: { Authorization: `Bearer ${KEY}` } }).then((r) => r.json()); } while (v.status !== "done" && v.status !== "error"); console.log(v.videoUrl, v.posterUrl, v.og);
pythonimport os, time, requests KEY = os.environ["PAGETOVID_API_KEY"] H = {"Authorization": f"Bearer {KEY}"} r = requests.post("https://pagetovid.com/api/v1/videos", headers=H, json={"url": "https://your-site.com", "goal": "ad"}).json() while True: time.sleep(5) v = requests.get(r["statusUrl"], headers=H).json() if v["status"] in ("done", "error"): break print(v["videoUrl"], v["posterUrl"], v["og"])
401 — invalid or missing API key.402 — out of credits. Top up on pricing.400 — invalid input (a url is required).Free credits to start — generate your first video by API in minutes.
Create an API key →