Agents & API
A programmatic render API built for agents: deterministic, computable pricing, and scoped keys with bounded spend — so an agent can estimate cost and render without a human in the loop.
worker_pending status until the raster worker ships — see status. We don't claim an uptime SLA yet.Organizations & service accounts
- An Organization is the billing entity — it owns the credit ledger. Every user automatically has a personal org.
- A Service account is an agent identity under an org: a scoped API key with an optional spend cap and expiry. It's a bounded mandate — a human grants an agent the right to spend up to $X on specific operations.
Get a key
Create a service account from your dashboard: Account → Service Accounts. Pick a name, scopes, and an optional spend cap. The key (pp_sa_…) is shown once — copy it then; only a hash is stored.
Authenticate
Send the key as a bearer token:
Authorization: Bearer pp_sa_xxxxxxxxxxxxxxxx
Scopes
| Scope | Grants |
|---|---|
render:create | Submit renders and spend credits on them |
render:read | Read render jobs and fetch artifacts |
scene:validate | Validate a scene without rendering it (free) |
inference:invoke | Generate designs through /v1/inference |
mcp:invoke | Drive the canvas over MCP (/mcp, /rpc) and join collab rooms |
graph:propose | Propose design-graph candidates for admin review — renders each one and spends credits |
A request without one of the required scopes is rejected with insufficient_scope. A spend cap is enforced before a render is held — once a key has charged up to its cap, further renders return 402.
Pricing is computable
Cost is deterministic, so an agent can bound it before calling:
credits = ceil(duration_s × fps_factor × resolution_factor × format_factor)
1 credit = 1s of 1080p/30 MP4 = $0.015
See the full table + calculator on the pricing page.
Start here: install the render skill
One file with the whole render contract — auth, the estimate → submit → poll flow, the scene geometry rules, costs and error codes. Written for agents; no account needed to read it.
mkdir -p ~/.claude/skills/pinepaper-cloud-render
curl -o ~/.claude/skills/pinepaper-cloud-render/SKILL.md https://cloud.pinepaper.studio/skills/pinepaper-cloud-render/SKILL.md
Or read it in the browser: /skills/pinepaper-cloud-render/SKILL.md
REST endpoints (/v1)
| Endpoint | |
|---|---|
POST /v1/renders:estimate | live · free exact credit + USD cost |
POST /v1/scenes:validate | live · free schema + limit diagnostics |
POST /v1/renders | SVG live submit — SVG renders & bills now; raster pending |
GET /v1/renders/{id} | live job status |
GET /v1/renders/{id}/artifact | live the rendered artifact |
GET /v1/renders/{id}/request | live the retained inputs — scene, export profile, claimed source |
Estimate a render
curl -X POST https://cloud.pinepaper.studio/v1/renders:estimate \
-H "Authorization: Bearer pp_sa_…" \
-H "Content-Type: application/json" \
-d '{"exportProfile":{"durationSeconds":10,"fps":30,"resolution":"1080p","format":"mp4"}}'
# → { "ok": true, "credits": 10, "priceUsd": 0.15, "breakdown": {…} }
Validate a scene
curl -X POST https://cloud.pinepaper.studio/v1/scenes:validate \
-H "Authorization: Bearer pp_sa_…" \
-H "Content-Type: application/json" \
-d '{"scene":{"canvas":{"width":1920,"height":1080},"layers":[…]}}'
# → { "valid": true, "diagnostics": [], "itemCount": 12, "dimensions": {…} }
Render a scene (SVG)
curl -X POST https://cloud.pinepaper.studio/v1/renders \
-H "Authorization: Bearer pp_sa_…" \
-H "Content-Type: application/json" \
-d '{"scene":{…},"exportProfile":{"resolution":"1080p","format":"svg","durationSeconds":5,"fps":30},
"source":{"provider":"anthropic","model":"claude-sonnet-5","prompt":"a midnight rooftop jazz poster"}}'
# source is REQUIRED: a submit without source.model or source.provider returns
# 422 SOURCE_REQUIRED, so every artifact can be traced back to what produced it.
# → { "ok": true, "status": "succeeded", "credits": 2, "priceUsd": 0.03,
# "cached": false, "statusUrl": "…/v1/renders/rnd_…",
# "artifactUrl": "…/v1/renders/rnd_…/artifact" }
# Then GET the artifactUrl for the SVG. A raster format returns 503 worker_pending.
Record what produced the design
Send an optional source block with a render and it is stored with the job and returned on the status endpoint, the retained request, and the user's Renders tab. The render API receives a finished scene, so the model and the instruction behind it are only knowable if you say so — without it, a delivered artifact has no history.
curl -X POST https://cloud.pinepaper.studio/v1/renders -H "Authorization: Bearer pp_sa_…" -H "Content-Type: application/json" -d '{"scene":{…},"exportProfile":{…},
"source":{"prompt":"a midnight rooftop jazz poster",
"provider":"openrouter","model":"anthropic/claude-sonnet-5",
"templateId":"tpl_42","conversationId":"conv_9",
"app":"pinepaper-studio@1.4.0"}}'
# The inputs come back whole:
curl https://cloud.pinepaper.studio/v1/renders/rnd_…/request -H "Authorization: Bearer pp_sa_…"
# → { "version": 1, "scene": {…}, "exportProfile": {…}, "source": {…},
# "frames": { "source": "engine", "count": 60, "retained": false } }
Errors use one diagnostic vocabulary everywhere — { code, severity, target, fix } — plus service codes INSUFFICIENT_CREDITS, LIMIT_EXCEEDED.
MCP tools
The same capabilities are exposed as MCP tools for Claude Desktop and other MCP clients via https://cloud.pinepaper.studio/mcp/v1:
| Tool | |
|---|---|
pinepaper_estimate | live · free |
pinepaper_validate | live · free |
pinepaper_render | SVG live · raster pending |
{
"mcpServers": {
"pinepaper-cloud": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://cloud.pinepaper.studio/mcp/v1"]
}
}
}
See also: pricing · status · security · general docs.