---
title: "Render the dashboard synchronously and return the image bytes inline."
method: POST
path: "/v1/dashboards/{id}/renders/inline"
tags: ["renders"]
---

# Render the dashboard synchronously and return the image bytes inline.

`POST /v1/dashboards/{id}/renders/inline`

## Request

- Base URL: `http://localhost:8080`
- URL: `http://localhost:8080/v1/dashboards/{id}/renders/inline`
- Auth: one of:
  - API key in cookie `dvt_session`
  - HTTP bearer

Renders the dashboard and returns the **PNG/PDF bytes directly in the response body** —
no object storage, no polling. The "see what you built" path for agents and tooling: a
caller gets the artifact back to analyze immediately. Unlike the async `POST …/renders`
(which queues to R2), this holds the request open while the page renders (live panels can
take tens of seconds). Same auth + tenancy + per-org render budget as `createRender`; any
org member may render a dashboard they can view, render sessions may not. Returns **503**
problem type `render-unavailable` while no render service is configured.
The per-org hourly budget is operator-configurable (`RENDER_RATE_LIMIT`; default 10/hour on SaaS, no hourly cap in the native app).

Set `includeSummary: true` (DVT-4428) to get back a JSON envelope — the image plus a
machine-readable per-panel render summary — instead of raw bytes, so a caller can tell a
panel that mounted-but-drew-nothing apart from one that actually rendered data without a
vision read of the image alone. Omitted or false: byte-identical to today's raw-bytes
response.

## Request body

- CreateRenderRequest: All fields optional — an empty body renders the current version as a 1280×800 PNG.
  - `purpose` 'validation': Async renders only (DVT-1364); rejected on `/renders/inline`. Only accepted in the Snowflake native app (render_app_stage) — a non-native-app deployment 400s regardless of caller role, since `source='validation'` is not a retention category there. `validation` stores the render as an expiring release-check render (deleted after `RENDER_VALIDATION_RETENTION_HOURS`, default 24) instead of a personal `user` render (which expires after `RENDER_USER_RETENTION_HOURS`, default the validation TTL); in the native app it additionally requires the admin-ranked `render:validate` capability (403 for a non-admin caller there). Any other value is 400.
  - `format` 'png' | 'pdf'
  - `revision` integer: Dashboard revision to render. Default — the current version, pinned at request time.
  - `width` integer: Viewport width in px.
  - `height` integer: Viewport height in px.
  - `page` integer: Zero-indexed page of a multi-page dashboard to capture. Default 0 (the first page); single-page dashboards ignore it. An in-range value past the last page clamps to the last page. Each render captures one page — to capture every page, request a render per page index.
  - `panelId` string: Optional panel id to render in isolation (DVT-860). When provided, the artifact captures only the named panel rather than the full page; the R2 key gains an `-el-<enc>` segment so panel artifacts never collide with whole-page artifacts. The artifact's own dimensions are the PANEL's, not the viewport's (DVT-4358): the panel is laid out edge-to-edge at `width` and the capture is clipped to its bounding box, so a PNG comes back `width` × 2 (the capture device pixel ratio) wide and as tall as the panel. `height` sizes only the viewport the panel is laid out in — it does not bound the image. Do not assume `width` × `height` × 2. The server validates only that the value is non-empty; panel-id resolution against the dashboard spec happens in the render page (client-side). If the id does not match any panel, the render will transition to `failed` rather than returning a 4xx error. When absent, the whole page is rendered (existing behavior, byte-identical artifact key).
  - `includeSummary` boolean: Only honored by `POST /renders/inline` (DVT-4428); ignored by the async `createRender`. When true, the 200 response is a JSON envelope carrying the image plus a machine-readable per-panel render summary, instead of raw artifact bytes — lets an agent verify a render (e.g. "drew 0 points") without a vision read of the image alone. Default false, byte-identical to today's behavior.

## Response `200`

The rendered artifact — raw bytes by default, or a JSON envelope (image + render summary) when the request set `includeSummary: true` (DVT-4428).

- RenderInlineSummaryEnvelope: Only returned by `POST /renders/inline` when the request set `includeSummary: true` (DVT-4428). The API passes this through verbatim from the render service — the summary's internal shape (per-panel `state`/`pointsDrawn`/warnings) is versioned by the render service, not this contract; treat `summary` as an opaque, evolving object beyond the one declared `schemaVersion` field.
  - `contentType` string, required: The MIME type of `image` once decoded, e.g. `image/png`.
  - `image` string, byte, required: Base64-encoded artifact bytes.
  - `summary` object, nullable, required: Machine-readable per-panel render summary. `null` when the render service could not collect one (DVT-4428) — the artifact still succeeded. `schemaVersion` is the only field this contract declares; everything else is opaque and versioned by the render service, not this contract.
    - `schemaVersion` integer, required: Version of the render service's internal summary shape.

## Other responses

- `400`: Malformed request.
- `401`: Missing, invalid, or expired session.
- `404`: Resource does not exist.
- `429`: Per-org hourly render budget exhausted (`rate-limited`). The cap is `RENDER_RATE_LIMIT` (default 10/hour on SaaS; 0 = no hourly cap, the native-app default). The budget 429 carries no `Retry-After` header (the separate per-actor `RateLimitDefault` 429 does).
- `502`: The render service failed to produce the artifact.
- `503`: Problem type `render-unavailable` — no render service is configured.

---

[API](https://skmtc.dev/dvt/apis/dvt-rest-api.md) · [All operations](https://skmtc.dev/dvt/apis/dvt-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dvt/apis/dvt-rest-api/revisions/00016f504165?raw)
