Use Pitchstage with AI agents
Claude Code · Claude Desktop · Cursor · any MCP client · or straight HTTP. For the full product walkthrough see the guide; for every endpoint see the API reference.
Pitchstage is built to be driven by an agent. Point it at your product — a handful of screenshots and one paragraph about what you shipped — and it plans and renders a narrated demo video, a LinkedIn carousel, and launch copy. The whole engine is exposed two ways: an MCP server (the agent gets typed tools and can see preview frames), or the /v1 REST API (any agent that can make HTTP calls). Both use the same two-phase loop: a cheap, read-only plan you iterate on, then one billable render.
1. First: mint an API key
In the app open Settings → API keys → Create key. Pick scopes and a monthly spend cap:
plan— read-only and free. The agent can ingest, plan, and inspect preview frames but can never spend money. Safe to hand an autonomous agent.render— billable. Needed to actually produce a video.
The raw key pk_live_… is shown once — copy it. Defaults per key: 60 requests/min and a $5/mo spend cap. All requests authenticate with Authorization: Bearer pk_live_….
2. The fast path — add the MCP server
One package — @pitchstage/mcp — run over npx, authenticated with your key in the PITCHSTAGE_API_KEY env var. Pick your client:
Claude Code
One command:
claude mcp add pitchstage \ --env PITCHSTAGE_API_KEY=pk_live_… \ -- npx -y @pitchstage/mcp
Claude Desktop
Settings → Developer → Edit Config, then add to claude_desktop_config.json:
{
"mcpServers": {
"pitchstage": {
"command": "npx",
"args": ["-y", "@pitchstage/mcp"],
"env": { "PITCHSTAGE_API_KEY": "pk_live_…" }
}
}
}Cursor
Add the same block to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project). Identical shape to the Claude Desktop config above.
Restart the client. (Optional base-URL override for self-host / staging: PITCHSTAGE_API_URL, default https://pitchstage.ai/api.) The agent now has seven tools:
| Tool | What it does |
|---|---|
pitchstage_create_project | create a project from a goal → presigned upload URLs for your screenshots |
pitchstage_plan | run the director without rendering → resolved plan + fit-score + preview frames returned as inline images the agent can SEE |
pitchstage_render | commit a plan → fork a variant + enqueue the render |
pitchstage_get_render | inspect a render: status, output URLs, transcript, poster, the plan it used |
pitchstage_list_variants | list a project’s render variants |
pitchstage_compose | one composer turn: natural language → a proposed EditPlan (never auto-applies) |
pitchstage_apply | apply an EditPlan’s ops; render-tier edits enqueue a scoped re-render |
The loop that makes agents good at this
create_project → upload screenshots → plan → (look at frames + fit-score, tweak, plan again) → render → get_render
Because plan is free and returns the preview frames as images, the agent can actually look at the composition, read the fit score and warnings[], adjust the plan, and re-plan — all before spending a single render. Iterate on plan; render once.
3. Without MCP — drive the /v1 API directly
Any agent that can make HTTP calls can run the whole flow. Base URL https://pitchstage.ai/api; every request carries Authorization: Bearer pk_live_…. Five steps:
Step 1 — create a project (returns presigned upload URLs)
POST /v1/projects
{ "goal": "30s launch teaser for developers",
"features": [{ "name": "Inbox", "screenshots": ["a.png", "b.png"] }] }
→ 201 { "project": { "id": "prj_…" },
"uploads": [{ "screenshot": "a.png", "uploadUrl": "https://…r2…?X-Amz-Signature=…", … }] }Step 2 — upload each screenshot (this is where agents trip)
Send each file as a plain PUT of the raw bytes to its uploadUrl, setting only a matching Content-Type. Add no other headers — no x-amz-*, no checksum header. The URL is signed for exactly that request; an extra header changes the signature and the upload 403s with SignatureDoesNotMatch.
curl -X PUT --upload-file a.png \ -H "Content-Type: image/png" \ "https://…r2…?X-Amz-Signature=…" # → 200. No other headers.
⚠️ If you upload with a stock S3 SDK (boto3, aws-sdk-js), it may auto-add a checksum header and 403. Use a bare HTTP PUT — that is the reliable path for a presigned URL.
Step 3 — plan (free, read-only)
POST /v1/projects/{id}/plan → 200 { "intent", "director", "scenes",
"fit", "estimate", "warnings", "previewFrames" }Read fit (0–1) and warnings[]; look at previewFrames. Re-plan with an adjusted body until you like it — it costs nothing.
Step 4 — render (billable) → get a renderId
POST /v1/projects/{id}/render → 202 { "renderId": "art_…", "status": "queued" }Quality gate: if the plan’s scored fit is below the floor (default 0.35), render is refused with 422 LK_107 and the plan’s gaps — so a weak plan can’t silently burn a render. Raise the score on the free plan step, or send {"acknowledgeLowFit": true} to override.
Step 5 — poll the render result
Poll GET /v1/renders/{renderId} — note it’s /v1/renders/…, not /v1/artifacts/… (a common wrong guess, since the id is art_-prefixed). When status is ready, outputs holds the final video, captions, and poster URLs.
GET /v1/renders/art_… → 200 { "status": "ready",
"outputs": [{ "kind": "video", "url": "https://cdn…/master.mp4" }, …] }Prefer server-sent events over polling? GET /v1/renders/{id}/events relays progress. The full machine-readable spec is at https://pitchstage.ai/api/v1/openapi.json — point your agent at it to self-discover every field.
4. Tips for agents
- Iterate on
plan, render once. Planning is free and returns preview frames + a fit-score; rendering costs money. Converge on the plan first. - Hand autonomous agents a
plan-scope key. It physically cannot trigger a billable render — a clean guardrail for unattended runs. - Trust the
warnings[]. The director reconciles incoherent input (clamps length, drops an unusable layout) and tells you what it changed instead of failing. - Scoped regenerate. Refresh just one scene, the audio, the video, or a caption via
POST /v1/artifacts/{id}/regenerate— no full re-render. - Handle 429. Rate-limited responses include a
Retry-Afterheader — back off by that many seconds.
Q&A
Which is better — MCP or the API?
/v1 API is for any other agent, a script, or CI.My upload keeps returning 403 SignatureDoesNotMatch.
x-amz-*/checksum header added by an S3 SDK. Use a plain HTTP PUT of the bytes with only Content-Type set. Nothing else.I get 404 fetching my render.
GET /v1/renders/{renderId}, not /v1/artifacts/{id}. The render id is art_-prefixed but the result lives under /v1/renders/….Is planning really free?
plan is read-only: it runs the director and returns preview frames + a fit-score with no render. You only pay on render. That’s what keeps an agent’s iterate-then-commit loop cheap.Can I set a hard spend limit?
plan-scope key can’t spend at all.Is my uploaded data stored?
Next: the full API reference (or /api/v1/openapi.json), the product guide, or your API keys to get started.