Render a Slide

Three deterministic render endpoints, each tailored to a different input shape — all $0.05 per slide, all sub-second. For multi-slide decks, see POST /v1/render/intent/deck.

Three render endpoints

200/422

POST /v1/render/auto — brief

Brief → SSG intent engine → deterministic render. ~<1s, $0.05. Bounded — never escalates. Unroutable briefs return a free intent_unroutable 422 (cost = 0).

200/422

POST /v1/render/intent — structured intent

The REST mirror of the MCP create_slide tool. Render a typed form, an exact catalog prior, or a full AuthorSSG document. $0.05 — or pass preview:true for a FREE ephemeral PNG.

200

POST /v1/render/code — python-pptx

Your python-pptx in a secure sandbox. Pixel-exact control. $0.05, ~0.5s. A free dry_run validates before you commit.

POST/v1/render/auto

Brief → SSG intent engine → deterministic render. Bounded $0.05 — never escalates to a slower or more expensive engine. Charges only on a usable render; unroutable briefs return an intent_unroutable envelope at no cost.

Parameters

NameTypeRequiredDescription
briefstringrequiredNatural language description of the slide. The SSG intent engine routes it to a deterministic render pattern.
theme_idstringoptionalTheme id (default "slideforge_standard"). Built-ins via GET /v1/themes (slideforge_standard, consulting_graphite, dark_keynote, product_bold, technical_lab, education_warm, healthcare_calm, scientific_paper, sales_warm), or a saved custom theme id.
namestringoptionalHuman-readable name for the slide. Auto-generated if omitted.
allow_fabricationbooleanoptionalDefault false. A data brief (a form like kpi_metrics needing values) returns would_fabricate at cost 0 rather than invent numbers; set true to let the brief author them (fidelity=ai_completed).
allow_low_confidencebooleanoptionalDefault false. A brief that doesn't match a form clearly returns needs_confirmation + candidates at cost 0; set true to render the top guess and bill it.
dry_runbooleanoptionalDefault false. true returns a free cost:0 validation forecast (status / warnings / errors) with no job, PPTX, or billing — a pre-commit check.

Response

200
{
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "complete",
  "engine": "auto",
  "cost": 0.05,
  "form": "timeline_roadmap",
  "fidelity": "mixed",
  "latency_ms": 840
}

Examples

curl -X POST https://api.slideforge.dev/v1/render/auto \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brief": "Three priorities for Q2: stabilize cash by fixing AR aging, launch the partner onboarding flow, and hire two senior engineers.",
    "theme_id": "slideforge_standard"
  }'

Downloading your file

Response bodies carry no download credentials. Fetch the file with GET /v1/jobs/{job_id}/pptx using your normal Bearer key (ownership-checked) — or mint a short-lived, single-use shareable link with POST /v1/jobs/{job_id}/download-url.

Brief-surface failure shape

When the brief does not ground a render pattern with confidence, /v1/render/auto returns a Problem+JSON 422 with code intent_unroutable. Nothing is charged, and remedy tells the agent what to add. A data-bearing brief (a form like kpi_metrics that needs values) returns status: "would_fabricate" (cost 0) rather than invent numbers — send the values as a typed intent (form + data) to render them verbatim, or set allow_fabrication: true to let the brief author them (fidelity: ai_completed).

{
  "type": "https://docs.slideforge.dev/errors/intent_unroutable",
  "title": "Intent could not be routed",
  "status": 422,
  "detail": "Brief is too thin to ground a form — name the metrics/comparison and the decision the slide should drive.",
  "code": "intent_unroutable",
  "actionable": true,
  "remedy": "Supply the concrete data, or call browse_catalog(type=schema, family=<form>) for the form's data shape."
}
POST/v1/render/intent

Deterministic SSG render from a structured intent — the REST mirror of the MCP create_slide tool. Provide ONE of: form (+ typed content), prior_id (+ content) to render an exact catalog prior, author_ssg for a full document, or a prose brief. $0.05 per slide.

Parameters

NameTypeRequiredDescription
formstringoptionalIntent form (e.g. kpi_metrics, comparison_matrix). Discover forms via GET /v1/catalog/forms and a form's typed-field JSON Schema via GET /v1/catalog/forms/{form}.
variantstringoptionalOptional variant within the form (e.g. delta_scoreboard) — pins the exact layout. See the form's contract.
dataobjectoptionalThe form's typed payload (e.g. { metrics: [...] }), copied verbatim — never re-derived. Shape per GET /v1/catalog/forms/{form}.
headlinestringoptionalAssertion-style slide title — plus context / takeaway / caution / source_note where the form binds them.
prior_idstringoptionalPower path: render an exact catalog prior verbatim (pair with content to fill its slots). Get prior_ids from GET /v1/catalog.
author_ssgobjectoptionalExpert path: a full AuthorSSG scene-graph document — LLM-free, renders exactly what you specify.
briefstringoptionalProse fallback. With only a brief, this behaves like /v1/render/auto.
theme_idstringoptionalTheme id (default "slideforge_standard"); see GET /v1/themes.
namestringoptionalHuman-readable slide name.
previewbooleanoptionalDefault false. true returns a FREE ephemeral PNG — no job, no charge, nothing downloadable. Eligible only for prior_id or author_ssg inputs; form/brief/image inputs return 400 (render them for $0.05).
dry_runbooleanoptionalDefault false. true returns a free cost:0 validation forecast (status / fidelity_forecast / warnings / errors) with no job, PPTX, or billing.
allow_fabricationbooleanoptionalBrief mode only. Let a bare brief on a DATA form author the numbers (fidelity=ai_completed) instead of returning would_fabricate.
allow_low_confidencebooleanoptionalBrief mode only. Render the top route guess instead of returning needs_confirmation + candidates.
allow_truncationbooleanoptionalDefault false. Render the capacity subset when you supply more items than a form holds (fidelity=verbatim_truncated) instead of a blocking error.

Response

200
{
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "complete",
  "engine": "auto",
  "cost": 0.05,
  "form": "timeline_roadmap",
  "fidelity": "mixed",
  "latency_ms": 840
}

Examples

curl -X POST https://api.slideforge.dev/v1/render/intent \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "form": "kpi_metrics",
    "variant": "delta_scoreboard",
    "headline": "Q1 performance ahead of plan; AR aging needs action",
    "context": "Exec committee — Q1 2026",
    "data": { "metrics": [
      {"label": "Revenue", "value": "$12.4M", "delta_value": "+18% YoY", "delta_tone": "good", "emphasis": "primary"},
      {"label": "New clients", "value": "847", "delta_value": "+23%", "delta_tone": "good"},
      {"label": "Days in AR", "value": "52", "delta_value": "+6", "delta_tone": "bad"}
    ]},
    "theme_id": "slideforge_standard"
  }'

Free preview — preview: true

Pass preview: true with a verbatim input (prior_id or author_ssg) to get a free ephemeral PNG — no job is created, nothing is charged, and there is nothing to download. Use it to show quality before committing to a paid render. Briefs and images are not eligible (they need the paid engine) and return 400.

# Free ephemeral PNG — no job, no charge, nothing downloadable.
curl -X POST https://api.slideforge.dev/v1/render/intent \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prior_id": "kpi_metrics_delta_scoreboard",
    "theme_id": "slideforge_standard",
    "preview": true
  }'
{
  "preview": true,
  "preview_url": "/v1/files/_ephemeral/preview-9f2a.png?sig=abc&exp=1711036800",
  "engine": "intent",
  "form": "kpi_metrics",
  "latency_ms": 96
}

Discovering forms + priors

GET /v1/catalog/forms lists every form (with its when-to-use + typed fields); GET /v1/catalog/forms/{form} returns one form's machine-readable JSON-Schema contract. GET /v1/catalog browses catalog priors (each carries a sample content and brief). The MCP browse_catalog tool is the agent-side equivalent.

POST/v1/render/code

Run python-pptx in a secure sandbox and get a PPTX + PNG preview. Define build(prs) — or build(prs, slide) when chrome is supplied. All python-pptx helpers plus the widget toolkit are available; dangerous imports are blocked; 30s timeout. $0.05 per render, ~0.5s.

Parameters

NameTypeRequiredDescription
codestringrequiredPython that defines build(prs) — or build(prs, slide) when chrome is supplied. All python-pptx helpers (add_text_box, add_box, add_icon, …) plus the widget toolkit are available. Dangerous imports are blocked; 30s timeout. Required unless job_id is given.
job_idstringoptionalA previous render/code job — loads its stored code so you can patch it with replacements.
replacementsarrayoptionalList of {old, new} string replacements to apply to the loaded code. Requires job_id.
theme_idstringoptionalTheme ID for chrome + colors.
chromeobjectoptionalChrome overlays: {title, subtitle, kicker, footer, source, page_number, classification}.
namestringoptionalHuman-readable job name.
verifystringoptionalVerification tier: off | lint (default — static geometry linter + composer content validators, no LLM) | lint+vlm (adds a VLM second-look, ~+8s) | full.
dry_runbooleanoptionalDefault false. When true, run the verify tier and return status:validated with warnings / errors at cost:0 and NO PPTX — a free pre-commit check. Fix errors, then render for real.
include_previewstringoptionalEmbed preview inline: none (default), small (256px), default (512px), full.

Response

200
{
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "complete",
  "engine": "sandbox",
  "warnings": [],
  "cost": 0.05,
  "latency_ms": 480
}

Examples

curl -X POST https://api.slideforge.dev/v1/render/code \
  -H "Authorization: Bearer sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "def build(prs, slide):\n    add_text_box(slide, 0.5, 0.5, 9, 1, \"Q1 Performance\", font_size=32, bold=True)\n    add_box(slide, 0.5, 2, 4, 2, fill_color=\"#1E40AF\")",
    "chrome": {"title": "Q1 2026 Performance", "footer": "Confidential"},
    "theme_id": "slideforge_standard",
    "verify": "lint"
  }'

Quality signal — status, warnings, errors

The verify tier returns the same diagnostic shape as the SSG path. errorsare structural bugs in your code — geometry overlaps/off-canvas and composer arithmetic (a waterfall that doesn't reconcile).warnings are cosmetic notes and any VLM visual read; they never block. A render with no errors is status: "complete" and bills $0.05; one with errors isstatus: "completed_with_errors" and is free — same usable-or-free promise as every path. Because the code is yours, we always return the rendered PPTX either way.

Free pre-commit check — dry_run: true

Pass dry_run: true to run the verify tier (static geometry linter + composer content validators) and get back status: "validated" with warnings / errors at cost: 0 and no PPTX. Fix any errors, then call again with dry_run: false to render for real.