Create an email-report schedule (Snowflake native app only).
Stores a cadence, timezone and recipient list for emailing this dashboard (or one of its pages) as an inline HTML report (DVT-4266). Snowflake-native only — the routes are not mounted outside snowflake mode, so every verb here 404s there. Requires dashboard:write.
THIS ROUTE ANSWERS 404 feature-disabled ONLY WHEN THE SURFACE IS OFF. Every verb under /v1/dashboards/{id}/email-schedules shares one gate — create, list, get, patch, delete, run and setup — the editionCapabilities.unattendedSchedules cell. DVT-4490 ships that cell TRUE wherever emailSchedule is true, the normal Snowflake native-app case, so a shipped install answers normally here, not 404. When the refusal does fire it precedes the path parse and the authorization load, so it is identical for a real schedule id and an invented one.
404 survives for exactly two operator-facing reasons: DVT_UNATTENDED_SCHEDULES_ENABLED=false set on BOTH dvt-api and dvt-engine (an explicit opt-out, not the shipped default), or an edition where emailSchedule itself is false (gallery/enterprise — the routes are not even mounted there). Stored rows are unaffected either way — this is a switch, not a migration.
POST /v1/dashboards/{id}/email ("Email me this report now") remains the on-demand alternative regardless of this cell. Clients must gate every schedule affordance on the capability cell rather than assume a fixed answer from this route's existence. The paragraph below describes the behavior every non-disabled install returns.
Behind the cell: schedules fire on their own once a Snowflake admin creates their task. GET .../{sid}/setup returns the exact statements; taskState reports what dvt has observed: absent until a run arrives, confirmed once one has. Until an admin runs them the schedule is stored and previewed and nothing arrives; POST .../run always sends immediately on the caller's own live session. No ticker runs, in any edition - an unattended send is driven by a CONSUMER-OWNED Snowflake task, which is what gives it a real Snowflake identity without dvt holding a standing IMPERSONATE ON USER grant (ADR-0069 Amendment 2, DVT-4300). A scheduled report embeds the same chart images an interactive send does — the render is server-side, from the rows dvt already holds: the ones the consumer's task staged for this run, plus any panel carrying its own inline data.rows in the spec (the backend-free shape, whose query is kept for the SQL inspector and is never executed — dvt stores no snapshot of a query result and never asks the task to re-read such a panel). Same limits either way: at most 12 chart images per report (charts past the email's render time budget or its body budget are noted in place), and a chart that fails falls back to its "view in dvt" note instead.
Supply either a raw 5-field cron or a preset — not both. nextRunAt is computed server-side from (cron, timezone) in the same transaction, so the SPA's client-side "next sends" preview can be cross-checked against it. Recipients are validated by exactly the same rules as POST /v1/dashboards/{id}/email.
A timezone that cannot be resolved to an IANA zone is a 422 (DVT-4321), not a 400; the failing value is echoed in a timezone extension field. A blank timezone, or "Local", normalizes to UTC rather than being rejected. The cadence must also fire no more than once every 15 minutes (DVT-4794, ADR-0069 Amendment 5 slice S3, D5) — a finer cadence is 422 cadence-too-fine, not stored.
Request
- Base URL: http://localhost:8080
- URL: http://localhost:8080/v1/dashboards/{id}/email-schedules
- Auth: one of:
- API key in cookie dvt_session
- HTTP bearer
Request body
Example request
{
"cron": "0 7 * * 1",
"timezone": "America/New_York"
}Response
Schedule created.
Changes
No recorded changes to this operation across all 1 revision of this API.