Rollstack MCP
The Rollstack MCP server enables AI agents to build, refresh, schedule, and send business reports and slide decks using company data from warehouses, BI tools, and spreadsheets. It supports creating decks from templates, managing schedules, and exporting to PowerPoint, Google Slides, or PDF while maintaining data lineage and governance.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://api.rollstack.com/public/v1/mcpWhat its tools do
59 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.
Read-only (32)
listReportsgetReportlistTemplatesshowTemplatesgetTemplatePickerCoversgetReportMessagelistReportRunsgetReportRunlistReportSyncsexportReportgetReportContentgetReportSlideImagesshowReportgetReportViewerSlideImageslistReportDatasheetsgetReportDatasheetDatagetReportParametersgetReportSchedulesgetReportEmailConfiglistReportEmailslistBurstsgetBurstRunlistBurstVariantsgetBurstVariantBatchlistConnectionssearchDashboardsgetDashboardsearchSpreadsheetsgetSpreadsheetlistSmtpConnectionslistFolderslistMembers
Can change data (27)
createReportduplicateReportupdateReportapplyReportTemplatesendReportMessageapproveReportMessageProposalcancelReportMessagerejectReportMessageProposalstartReportRuncancelReportRuncreateDatasetreplaceDatasetdeleteDatasetaddReportDatasheetscreateReportParametershareReportunshareReportupdateReportSchedulesupdateReportEmailConfigsendReportEmailsendReportTestEmailaddBurstVariantscreateBurststartBurstRunupdateBurstVariantRecipientsremoveBurstVariantssubmitFeedback
Checks and signals
Each line is separate evidence, not a trust score.
- Passed Endpoint answered the live check ·
- Passed Official MCP Registry namespace is tied to rollstack.com ·
- Passed Endpoint is on the registry namespace domain ·
- Warning Advertises resources/templates/list but does not implement it
- Availability 1 of 1 checks passed in 30 days
What you can do with it
- Build a quarterly business review deck from Tableau dashboards
- Refresh data in a weekly sales report and email it to the team
- Create one deck per region from a single template
- Schedule the board report to update every Monday
Source and maintenance
Protocol and capabilities
- Server
- rollstack 1.0.71
- MCP protocol negotiated in check
- 2025-11-25
- Tools
- 59 advertised
- Resources
- 2 advertised
- Resource templates
- Not advertised
- Prompts
- 3 advertised
{
"tools": {},
"prompts": {},
"resources": {}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
59 advertised
listReports — List reports
The reports the user can see, of every type, newest first. Each report's type tells which endpoints work on it: the slides agent, exports, content, datasheets, parameters, templates, duplicating and ownership transfer take SlideDeck reports only, and syncs take the other types only. You can filter by folderId, name and type; when several are set, all must match, and name matching ignores case. Answers up to limit reports, 50 by default and 200 at most, and a nextCursor: pass it as cursor for the next page, until it is null.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"query": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"business review"
],
"minLength": 1,
"description": "Only return reports whose name contains this text, ignoring case: `review` matches `Q3 Business Review`."
},
"type": {
"enum": [
"GoogleDocs",
"GoogleSlides",
"MicrosoftPowerPoint",
"MicrosoftWord",
"Email",
"UploadedPPTXFile",
"SlideDeck"
],
"type": "string",
"examples": [
"SlideDeck"
],
"description": "Only return reports of this `type`, such as `SlideDeck` for the reports that the slides agent, exports and datasheets work on."
},
"limit": {
"type": "integer",
"default": 50,
"maximum": 200,
"minimum": 1,
"description": "Maximum number of reports to return on this page, from 1 to 200. Defaults to `50`."
},
"cursor": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "Where to continue the list: pass the `nextCursor` returned with the previous page to get the next one. Omit it for the first page."
},
"folderId": {
"type": "string",
"examples": [
"a3d5e7f9-1b2c-4d6e-8f0a-1b2c3d4e5f6a"
],
"description": "Only return reports directly in this folder, by its `id` from `listFolders`. Reports in its subfolders aren't included."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getReport — Get report
A report of any type with its schedules, who it is shared with and who is emailed when a run fails. lastRunStatus and running tell how its latest run went and whether one is going, and appUrl opens it in Rollstack. type tells which other endpoints work on it.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}createReport — Create report
Creates a report of type SlideDeck, in a folder the user can see when folderId is set. It starts empty, in the look of a saved template from listTemplates when templateId is set, or of another report when templateDeckId is set: its theme, masters and layouts, without its slides. Ask the user which template to use when the organization has company templates.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Q3 business review"
],
"minLength": 1,
"description": "Name for the report, as members will see it in Rollstack. Leading and trailing spaces are removed, and it can't be blank."
},
"folderId": {
"type": "string",
"examples": [
"a3d5e7f9-1b2c-4d6e-8f0a-1b2c3d4e5f6a"
],
"description": "The folder to create the report in, by its `id` from `listFolders`; it must be one you can see. Members with access to the folder can then open the report too, with the access the folder gives them. If omitted, the report is created at the top level, outside any folder."
},
"templateId": {
"type": "string",
"examples": [
"rollstack-signature"
],
"minLength": 1,
"description": "A saved template the new report starts with, by its `id` from `listTemplates`: a company template or Rollstack's own. The report gets its theme, slide masters, layouts and slide size, with no slides. Leave out `templateDeckId` when you set it."
},
"templateDeckId": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "An existing report whose design the new report starts with, by its `id` from `listReports`: its theme, slide masters, layouts and slide size, but none of its slides or data. Its `type` must be `SlideDeck`, and you need at least view access to it. If neither this nor `templateId` is set, the report starts with no slides and Rollstack's default theme and layouts."
}
},
"additionalProperties": false
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}duplicateReport — Duplicate report
Copies a report of type SlideDeck with its slides, datasheets and email setup, as Duplicate in the app does, and answers the copy, which you own. Its schedules and direct shares are copied only when asked. Only members who may duplicate the report may: view access is enough. Each call makes another copy.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Q4 business review"
],
"minLength": 1,
"description": "Name for the copy, as members will see it in Rollstack. Leading and trailing spaces are removed, and it can't be blank."
},
"folderId": {
"type": "string",
"examples": [
"a3d5e7f9-1b2c-4d6e-8f0a-1b2c3d4e5f6a"
],
"description": "The folder to put the copy in, by its `id` from `listFolders`; it must be one you can add reports to. If omitted, the copy goes in the report's own folder, or for a burst's variant, in the burst's folder."
},
"copySchedules": {
"type": "boolean",
"default": false,
"description": "Also give the copy the report's schedules, so it updates on its own at the same times. Defaults to `false`."
},
"inheritSharing": {
"type": "boolean",
"default": false,
"description": "Also share the copy with everyone the report is shared with directly, at the same permission. Defaults to `false`, so only you can open it until you share it."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}updateReport — Update report
Renames a report of any type, moves it, or changes its timezone or failure notifications. Renaming a report that updates a file, such as a Google Slides presentation, also renames the file, as the app does. Only its editors may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"Q3 business review"
],
"minLength": 1,
"description": "New name for the report, as members will see it in Rollstack. Leading and trailing spaces are removed, and it can't be blank."
},
"folderId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"examples": [
"a3d5e7f9-1b2c-4d6e-8f0a-1b2c3d4e5f6a"
],
"description": "The folder to move the report to, by its `id` from `listFolders`; it must be one you can see. Pass `null` to move it to the top level, outside any folder. Members then get access to the report through the new folder, and the folders it's in, instead of the old one."
},
"timezone": {
"type": "string",
"examples": [
"America/New_York"
],
"description": "The report's new timezone. The slides agent uses it to tell today's date, and the report's emails show the time of its last successful update (`{{last_updated_at}}`) in it. On a report that updates a file, it's also the timezone of the file's date variables, unless the organization's `timezone` replaces it. It doesn't change the report's schedules, which each have their own `timezone`: change those with `updateReportSchedules`. An IANA timezone name, such as `America/New_York`."
},
"notifyOnFailure": {
"type": "boolean",
"description": "Whether Rollstack should email the report's owner when a scheduled run fails or some of its datasheets fail to refresh, copying everyone in `notificationMailingList`. Set it to `false` to stop these emails. Runs started in the app or with `startReportRun` never send them."
},
"notificationMailingList": {
"type": "array",
"items": {
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"examples": [
"jane@acme.com"
]
},
"maxItems": 100,
"description": "Email addresses to copy when Rollstack emails the owner about a failed scheduled run, while `notifyOnFailure` is `true`. The list you send replaces the current one; send `[]` to clear it. Each address must belong to an active member of the organization, ignoring case. Up to 100 addresses, with no duplicates."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}listTemplates — List templates
The templates the user can build a slide deck in: their company's, with who imported each and whether it is shared with the organization, then Rollstack's own. Pass a template's id as templateId to createReport or applyReportTemplate.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}showTemplates — Show templates
Shows the user the templates they can build a slide deck in, each with a preview of its look, when the client can show a picker. Pass reportId when they pick one for an existing report: each template then warns about the report's slides it has no layout for. Picking one sends you a message naming the template: then apply it with applyReportTemplate, or start a report in it with createReport's templateId, as the user asked. Answers the templates as listTemplates does, for clients that can't show the picker.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"query": {
"type": "object",
"properties": {
"reportId": {
"type": "string",
"description": "The report the user picks a template for, by its `id` from `listReports`: the picker warns about the slides each template has no layout for. Its `type` must be `SlideDeck`, and you need edit access to it. Leave it out when the user picks one for a new report."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getTemplatePickerCovers — Get template picker covers
The template covers the template picker shows, called by the picker itself. Use showTemplates instead. At most 10 templates a call.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"query"
],
"properties": {
"query": {
"type": "object",
"required": [
"templateIds"
],
"properties": {
"reportId": {
"type": "string",
"description": "The report the user picks a template for, by its `id` from `listReports`: the picker warns about the slides each template has no layout for. Its `type` must be `SlideDeck`, and you need edit access to it. Leave it out when the user picks one for a new report."
},
"templateIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 10,
"minItems": 1
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}applyReportTemplate — Apply template
Switches a report of type SlideDeck to a template's theme, slide masters, layouts and slide size, as the Templates drawer in the app does. Its slides keep their content and move to the template's matching layouts; the answer names the slides that had no match. A version saved just before, in the report's Version history, undoes it. Only its editors may, and not while the report is running or the slides agent is working on it.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"templateId"
],
"properties": {
"templateId": {
"type": "string",
"examples": [
"rollstack-signature"
],
"minLength": 1,
"description": "The template, by its `id` from `listTemplates`. Rollstack's own template has the fixed id `rollstack-signature`."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}getReportMessage — Get slides agent message
A message to the slides agent and its replies. Waits up to waitSeconds for the message to finish and answers as soon as it does, so call it again while the status is queued or running. A clarification reply asks questions: ask the user, then send the options they pick as answers in a new message on the same chat. A proposal reply changes nothing until it is approved: show the user what its proposal changes, then approve or reject it as they decide. Only the user who sent the message may read it, while they can edit the report.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"waitSeconds": {
"type": "integer",
"default": 20,
"maximum": 30,
"minimum": 0,
"description": "How long this call waits for the work to finish, in seconds: the message to the slides agent on `getReportMessage`, the run on `getReportRun`, the batch of variants being added on `getBurstVariantBatch`, the runs of a burst's variants on `getBurstRun`. It returns as soon as the work is done, or as things stand once the time is up, so call it again while `status` is still `queued` or `running`. `0` returns at once. Defaults to `20`; at most `30`."
}
}
},
"params": {
"type": "object",
"required": [
"id",
"messageId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
},
"messageId": {
"type": "string",
"description": "The message to the slides agent: the `messageId` that `sendReportMessage` returned. Only the user who sent the message can read, cancel or decide its proposals, and only while they can edit the report."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}sendReportMessage — Send message to slides agent
Asks the slides agent to build or change a report, or to answer a question about it, as the app's chat does. Answers the message's id at once: follow it with getReportMessage. Without chatId the message starts a new chat, which shows in the user's chat history in the app. With it, the message continues that chat and waits its turn while a reply is still generating. Several chats on a report can generate at once; an agent working on a part of the report another chat is editing works on something else or says so. For slides built from your own data, a connected dashboard or a spreadsheet, upload the data with createDataset, find the dashboard or Salesforce report with searchDashboards or the spreadsheet with searchSpreadsheets, add any of them with addReportDatasheets and pass the datasheet ids as datasheetIds. Only its editors may. At most 6 messages a minute per user.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"properties": {
"chatId": {
"type": "string",
"examples": [
"0e4c2b7a-9d1f-4a3b-8c5e-6f7a8b9c0d1e"
],
"description": "The chat to continue: the `chatId` returned for an earlier message. The agent reads the chat's earlier messages as context, and if it's still replying in that chat, your message waits its turn (`queued`). If omitted, the message starts a new chat, which shows in your chat history on the report in the app. Must be one of your own chats on this report."
},
"answers": {
"type": "array",
"items": {
"type": "object",
"required": [
"header",
"question",
"answers"
],
"properties": {
"header": {
"type": "string",
"examples": [
"Chart type"
],
"description": "The `header` of the question you're answering, copied unchanged from the `clarification` reply's `questions`."
},
"answers": {
"type": "array",
"items": {
"type": "string",
"examples": [
"Bar chart"
]
},
"minItems": 1,
"description": "The `label` of each option picked: one for a question whose `multiSelect` is `false`, one or more when it's `true`."
},
"question": {
"type": "string",
"examples": [
"Which chart should show revenue by region?"
],
"description": "The question you're answering, copied unchanged from the `clarification` reply's `questions`. With `header`, it tells Rollstack which question your picks are for."
}
}
},
"minItems": 1,
"description": "Your answers to the questions of a `clarification` reply, as when you pick options in the chat in the app: one entry per question you answer. Send them as the next message on the same chat, by passing its `chatId`. When a picked option offers a dashboard, table or spreadsheet, Rollstack adds it to the report as a datasheet before the agent goes on. To add a note, send it in `content` with the answers."
},
"content": {
"type": "string",
"default": "",
"examples": [
"Add a slide comparing revenue by region"
],
"maxLength": 10000,
"description": "Your message to the slides agent, as you would write it in the chat in the app: for example, slides to build or change, or a question about the report. On a report with no slides yet, the agent takes it as a request to build the report. Required unless you send `answers`; with them, it's sent after your answers as a note. At most 10,000 characters."
},
"slideIds": {
"type": "array",
"items": {
"type": "string",
"examples": [
"f1e2d3c4-b5a6-4978-8a1b-2c3d4e5f6a7b"
]
},
"maxItems": 100,
"minItems": 1,
"description": "The slides your message is about, as when you select slides in the app before writing in the chat. The agent knows you selected them and uses the datasheets on them for your request. Slide ids come from `getReportContent`. 1 to 100 slides of this report."
},
"datasheetIds": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"examples": [
"d7b9a1c3-e5f7-4a9b-8c1d-3e5f7a9b1c2d"
]
},
"maxItems": 100,
"minItems": 1,
"description": "Datasheets of this report for the agent to work from, on top of those on the slides in `slideIds`, as when you pick data in the chat in the app. To have the agent build slides from data you just added, pass the ids `addReportDatasheets` returned; for data already on the report, take them from `listReportDatasheets`. 1 to 100 datasheets of this report."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}approveReportMessageProposal — Approve slides agent proposal
Approves the proposal of a settings_proposal or email_send_proposal reply, as its Approve button in the app's chat does: Rollstack makes the change, or sends the email. Only approve what the user approved after seeing the reply's proposal. Answers the reply with the proposal's status: applied once the change is made, and queued for a send, which getReportMessage then follows through sending to sent, partially_sent, failed or unconfirmed, with its counts. Needs also slide_decks:email for an email change or send, and slide_decks:write for the rest. Approving a send answers 409 while the report is updating, such as after a filter change the same message asked for, and counts against the 5 email sends a minute, as sendReportEmail does. Only the user who sent the message may, while they can edit the report. A proposal already decided answers 409.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id",
"messageId",
"replyId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
},
"replyId": {
"type": "string",
"description": "The reply that makes the proposal: the `id` of a `settings_proposal` or `email_send_proposal` reply that `getReportMessage` lists for the message."
},
"messageId": {
"type": "string",
"description": "The message to the slides agent: the `messageId` that `sendReportMessage` returned. Only the user who sent the message can read, cancel or decide its proposals, and only while they can edit the report."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}cancelReportMessage — Cancel slides agent message
Stops a message to the slides agent: a queued one leaves the queue, and a running one stops. A finished one stays as it is. Only the user who sent it may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id",
"messageId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
},
"messageId": {
"type": "string",
"description": "The message to the slides agent: the `messageId` that `sendReportMessage` returned. Only the user who sent the message can read, cancel or decide its proposals, and only while they can edit the report."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}rejectReportMessageProposal — Reject slides agent proposal
Rejects the proposal of a settings_proposal or email_send_proposal reply, as its Reject button in the app's chat does: nothing changes. Answers the reply with the proposal's status, rejected for a change and cancelled for an email send. Only the user who sent the message may, while they can edit the report. A proposal already decided answers 409.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id",
"messageId",
"replyId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
},
"replyId": {
"type": "string",
"description": "The reply that makes the proposal: the `id` of a `settings_proposal` or `email_send_proposal` reply that `getReportMessage` lists for the message."
},
"messageId": {
"type": "string",
"description": "The message to the slides agent: the `messageId` that `sendReportMessage` returned. Only the user who sent the message can read, cancel or decide its proposals, and only while they can edit the report."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}listReportRuns — List report runs
The runs of a report of any type that ended, newest first, with how each ended, what started it and why it failed, for questions such as why last night's update failed. Answers up to limit runs, 20 by default and 200 at most, and a nextCursor: pass it as cursor for the next page, until it is null.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 200,
"minimum": 1,
"description": "Maximum number of runs to return on this page, from 1 to 200. Defaults to `20`."
},
"cursor": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "Where to continue the list: pass the `nextCursor` returned with the previous page to get the next one. Omit it for the first page."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getReportRun — Get report run
A run's status and the datasheets, or visualizations on a report of another type than SlideDeck, it could not refresh. Waits up to waitSeconds for the run to end and answers as soon as it does, so call it again while the status is running. A user's later run of the report reuses the id, so this describes the latest one.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"waitSeconds": {
"type": "integer",
"default": 20,
"maximum": 30,
"minimum": 0,
"description": "How long this call waits for the work to finish, in seconds: the message to the slides agent on `getReportMessage`, the run on `getReportRun`, the batch of variants being added on `getBurstVariantBatch`, the runs of a burst's variants on `getBurstRun`. It returns as soon as the work is done, or as things stand once the time is up, so call it again while `status` is still `queued` or `running`. `0` returns at once. Defaults to `20`; at most `30`."
}
}
},
"params": {
"type": "object",
"required": [
"id",
"runId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
},
"runId": {
"type": "string",
"description": "The run, by the `runId` that `startReportRun` returned. Runs of a report started by the same member share one id, so it always refers to that member's latest run of the report."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}listReportSyncs — List report syncs
The syncs of a report other than a SlideDeck, such as a Google Slides presentation or an email report: each chart, table or text it pulls from a source, with how it did the last time it updated and why it failed. Pass the failed ones' ids as `syncIds` to `startReportRun` to update only those. A SlideDeck report has datasheets instead and returns `400`.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}startReportRun — Start report run
Refreshes a report's data, or only some of its datasheets, then repairs failed calculations and the slides with AI. On a report of another type than SlideDeck, such as a Google Slides presentation, refreshes every sync, or only the `syncIds` given, instead, as Update in the app does, updating its file when it has one (an Email report has none). A run of the whole report then emails it when its email trigger is `all`; a run of only some `syncIds` never does. Answers the run's id at once; while a run of the report is already going, from the API, the app or its schedule, it answers that run's id with started false and starts nothing.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"body": {
"type": "object",
"default": {},
"properties": {
"syncIds": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"maxItems": 500,
"minItems": 1,
"description": "The syncs to update, from `listReportSyncs`, instead of the whole report, such as the ones whose `status` is `failed`. Each must be a sync of this report. A `paused` sync is skipped, as in the app. A run of only some syncs never emails the report. If omitted, the run updates the whole report. 1 to 500 ids. Only on reports other than `SlideDeck`, which has datasheets instead, so passing it on a slide deck returns `400`."
},
"datasheetIds": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"examples": [
"d7b9a1c3-e5f7-4a9b-8c1d-3e5f7a9b1c2d"
]
},
"maxItems": 500,
"minItems": 1,
"description": "The datasheets to update, from `listReportDatasheets`, instead of the whole report. Each must be a datasheet of this report. Unlike a run of the whole report, which reads every source again, a run of only some datasheets reuses the data last read from their sources: it reads a source again only if that data is missing or expired, or what the datasheet reads has changed, such as its source, its filters or the connection it reads with, as when you replace an uploaded file with `replaceDataset`. If omitted, the run updates the whole report. 1 to 500 ids. Only on reports whose `type` is `SlideDeck`: a report of another type has syncs instead, so passing it returns `400`."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}cancelReportRun — Cancel report run
Cancels a run of a report, whoever started it. Only its editors may. A run that already ended stays as it is.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id",
"runId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
},
"runId": {
"type": "string",
"description": "The run, by the `runId` that `startReportRun` returned. Runs of a report started by the same member share one id, so it always refers to that member's latest run of the report."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}exportReport — Export report
Exports a report as PDF or PowerPoint and answers a download link valid for 15 minutes. At most 10 exports a minute per user.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"format"
],
"properties": {
"format": {
"enum": [
"pdf",
"pptx"
],
"type": "string",
"description": "The kind of file to create. `pdf` is a PDF of the report's visible slides; hidden slides are left out. `pptx` is a PowerPoint file in which hidden slides are included but stay hidden, speaker notes are kept, and charts are images rather than editable charts."
},
"slideIds": {
"type": "array",
"items": {
"type": "string",
"examples": [
"f1e2d3c4-b5a6-4978-8a1b-2c3d4e5f6a7b"
]
},
"minItems": 1,
"description": "The slides to export, from `getReportContent` or a reply's `changedSlideIds`. The file keeps the report's slide order whatever order you list them in. Ids that are not slides of the report are ignored, and so are hidden slides in a PDF. If omitted, the whole report is exported."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}getReportContent — Get report content
What a viewer sees on a report's visible slides: titles, text, and each chart's and table's values. On a long report, pass slideIds for only the slides you need, such as a reply's changedSlideIds.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"slideIds": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"minItems": 1
}
],
"examples": [
"f1e2d3c4-b5a6-4978-8a1b-2c3d4e5f6a7b"
],
"description": "The slides to return, from a reply's `changedSlideIds` or an earlier `getReportContent` call. If omitted, every visible slide is returned. Hidden slides and ids that are not slides of the report are ignored. Up to 20 ids: repeat the parameter for each one, as in `?slideIds=a&slideIds=b`."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getReportSlideImages — Get slide images
Renders slides of a report as images, as viewers see them, so you can check how they look: text that overflows or overlaps, or a chart too small to read. After a message's turn, pass its replies' changedSlideIds. At most 10 slides a call; hidden slides are left out. Counts against the 10 exports a minute per user.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"query"
],
"properties": {
"query": {
"type": "object",
"required": [
"slideIds"
],
"properties": {
"slideIds": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 10,
"minItems": 1
}
],
"examples": [
"f1e2d3c4-b5a6-4978-8a1b-2c3d4e5f6a7b"
],
"description": "The slides to render, from `getReportContent` or a reply's `changedSlideIds`. Hidden slides and ids that are not slides of the report are ignored. 1 to 10 ids: repeat the parameter for each one, as in `?slideIds=a&slideIds=b`."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}showReport — Show report
Shows a report to the user in a viewer with every visible slide, when the client can show one, to browse it or review the slides the slides agent changed: pass the replies' changedSlideIds to open on the first of them and mark them all. Answers the slides' ids and titles. Clients that can't show the viewer can look at the slides with getReportSlideImages instead.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"changedSlideIds": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 1000
}
],
"description": "The slides the slides agent changed, from the replies' `changedSlideIds`, to open on the first of them and mark them all. Leave it out, or pass an empty list, to browse the report from its first slide."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getReportViewerSlideImages — Get report viewer slide images
The slide images the report viewer shows, called by the viewer itself. Use getReportSlideImages instead. At most 10 slides a call; hidden slides are left out.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"query"
],
"properties": {
"query": {
"type": "object",
"required": [
"slideIds",
"version",
"size"
],
"properties": {
"size": {
"enum": [
"thumbnail",
"full"
],
"type": "string",
"description": "A thumbnail for the strip, or the whole slide for the selected one."
},
"version": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991
},
"slideIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 10,
"minItems": 1
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}createDataset — Upload a file
Stores a CSV for the slides agent to build slides from: a header row, then at least one data row, at most 10 MB. Add it to a report with addReportDatasheets. Over MCP the CSV is written into the tool call, so send large files to this REST endpoint instead. Or send an Excel workbook (.xlsx, at most 10 MB) as multipart/form-data in the file field: it is stored as it is, with all its sheets, formatting and charts, and the user picks its sheets and ranges for a report in the app's editor. Legacy .xls, macro-enabled and password-protected workbooks are rejected. A workbook is read as saved: formulas show their saved results, and nothing is recalculated.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"name",
"csv"
],
"properties": {
"csv": {
"type": "string",
"examples": [
"region,revenue\nEMEA,1200000\nAmericas,2400000"
],
"minLength": 1,
"description": "The file's data, as CSV text: a header row naming the columns, then at least one row of data. With `replaceDataset`, it replaces the file's whole content, header included, and the uploaded file must be a CSV file. The header's names become the column names of the datasheets made from the file: a blank one becomes `Column N`, after the column's position, and a repeated one gets a `_2`, `_3` suffix. Values can be separated by commas, semicolons or tabs, detected from the header row. At most 10 MB."
},
"name": {
"type": "string",
"examples": [
"Q3 pipeline"
],
"maxLength": 255,
"minLength": 1,
"description": "A name for the uploaded file, which its datasheet takes when you add the file to a report with `addReportDatasheets`. Leading and trailing spaces are removed, and a name containing a `/` keeps only its last part: `exports/Q3 pipeline` is stored as `Q3 pipeline`. From 1 to 255 characters."
}
},
"additionalProperties": false
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}replaceDataset — Replace an uploaded file
Replaces an uploaded CSV file's rows, or a workbook's content with a new .xlsx sent as multipart/form-data in the file field. It keeps its id, and a CSV is never replaced by a workbook or the other way round. Reports built on it show the new content after their next run or message to the slides agent. An invalid file leaves the current one in place, and a sheet or range the new workbook no longer has fails its datasheets' reads. Only the user who created it may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"csv"
],
"properties": {
"csv": {
"type": "string",
"examples": [
"region,revenue\nEMEA,1200000\nAmericas,2400000"
],
"minLength": 1,
"description": "The file's data, as CSV text: a header row naming the columns, then at least one row of data. With `replaceDataset`, it replaces the file's whole content, header included, and the uploaded file must be a CSV file. The header's names become the column names of the datasheets made from the file: a blank one becomes `Column N`, after the column's position, and a repeated one gets a `_2`, `_3` suffix. Values can be separated by commas, semicolons or tabs, detected from the header row. At most 10 MB."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The uploaded file to replace or delete: the `id` returned by `createDataset`. Only the user who uploaded the file can replace or delete it; for anyone else, the request fails with a `404`, as if the file did not exist."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}deleteDataset — Delete an uploaded file
Deletes an uploaded CSV file or workbook. Reports built on it keep what they last showed, and their datasheets fail on the next read. Only the user who created it may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The uploaded file to replace or delete: the `id` returned by `createDataset`. Only the user who uploaded the file can replace or delete it; for anyone else, the request fails with a `404`, as if the file did not exist."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}listReportDatasheets — List report datasheets
The datasheets a report's charts and tables are built from, with their source and when each was last read.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getReportDatasheetData — Get datasheet data
The table a report's chart is drawn from: the datasheet's steps run over the copies stored at its sources' last reads; the source is never queried. Only the report's editors may: the table was read with an editor's credentials, can hold columns and rows the slides never show, and skips the source's row-level security. Fails for a `picture` datasheet (its `kind` in `listReportDatasheets`), which has no table. Also fails until every source it reads has been read, after a source's latest read failed, and once a stored copy expires, 30 days after its read. At most 30 reads a minute per user.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 200,
"maximum": 1000,
"minimum": 1,
"description": "The maximum number of rows to return, starting from the first row of the table. If the table has more, `truncated` is `true`. Can range from `1` to `1000`. Defaults to `200`."
}
}
},
"params": {
"type": "object",
"required": [
"id",
"datasheetId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
},
"datasheetId": {
"type": "string",
"description": "The datasheet whose table to read: an `id` from `listReportDatasheets`, or one of the `datasheetIds` returned by `addReportDatasheets`. It must be one of this report's datasheets. A datasheet that reads a picture, such as a dashboard tab added with `addReportDatasheets`, has no table, so the request fails."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}addReportDatasheets — Add sources to report
Adds sources to a report as datasheets, and answers their ids in the order of the sources. A source is a CSV file uploaded with createDataset, or a dashboard of a Looker, Metabase, Omni, Lightdash, Sigma, Tableau or Power BI connection: find it with searchDashboards, confirm it with the user, optionally check its tabs and charts with getDashboard, and add it by its connection, id and tabId from getDashboard's tabs, or from searchDashboards for a Sigma workbook found by a link (else the tab it opens on, a Power BI report's or Sigma workbook's first page). A dashboard comes in as one picture of the tab, read with the user's access to the connection, from which the slides agent can add its charts; a Tableau or Power BI dashboard's charts are listed when its picture is first taken. A source can also be a tabular or summary report of a Salesforce connection, found with searchDashboards and added by its connection and reportId: it comes in as a table of its rows, read with the user's access to the connection; a matrix or joined report is rejected. A source can also be a range of a Google Sheets or Excel file the user added in the app: find the file with searchSpreadsheets, take the sheet's id from getSpreadsheet, and pass the range inside the sheet in A1 notation, like A1:F20. A range comes in as a table, read with the user's own Google or Microsoft account on every run. Pass the ids as datasheetIds on sendReportMessage for the slides agent to build slides from them. Only the report's editors may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"sources"
],
"properties": {
"sources": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"required": [
"datasetId"
],
"properties": {
"datasetId": {
"type": "string",
"examples": [
"b2c4d6e8-f0a1-4b3c-9d5e-7f9a1b3c5d7e"
],
"description": "The uploaded CSV file to add: the `id` returned by `createDataset`. The datasheet contains the whole CSV as one table and is named after the file. It can be any uploaded CSV file of the report's organization, including one another member uploaded; an uploaded workbook is rejected."
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"connectionType",
"connectionId",
"dashboardId"
],
"properties": {
"tabId": {
"type": "string",
"examples": [
"12-overview"
],
"description": "The tab to add: one of the `tabs[].id` values from `getDashboard`, which for Tableau are a workbook's views, for Power BI a report's pages and for Sigma a workbook's pages, or the `tabId` of a Sigma workbook `searchDashboards` found by a link. The datasheet is a picture of that tab, named after it. If omitted, Rollstack adds the tab the dashboard opens on (the first view or page for Tableau, Power BI and Sigma), or, for a dashboard without tabs such as an Omni dashboard, the whole dashboard, named after it. A tab the dashboard doesn't have is rejected."
},
"dashboardId": {
"type": "string",
"examples": [
"128"
],
"description": "The dashboard to add: the `id` of a dashboard from `searchDashboards` on this connection. For Tableau and Sigma, it is a workbook, and for Power BI, a report."
},
"connectionId": {
"type": "string",
"examples": [
"c8e0a2b4-d6f8-4a0b-8c2d-4e6f8a0b2c4d"
],
"description": "The connection the dashboard is on: the `id` of a connection from `listConnections`. You must have access to the connection in Rollstack."
},
"connectionType": {
"enum": [
"Looker",
"Metabase",
"Omni",
"Lightdash",
"Tableau",
"PowerBI",
"Sigma"
],
"type": "string",
"description": "The type of the connection the dashboard is on: `Looker`, `Metabase`, `Omni`, `Lightdash`, `Sigma`, `Tableau` or `PowerBI`. It must match the connection's `type` in `listConnections`."
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"connectionType",
"connectionId",
"reportId"
],
"properties": {
"reportId": {
"type": "string",
"examples": [
"00O5e000008abcdEAA"
],
"description": "The report to add: the `id` of a `tabular` or `summary` report from `searchDashboards` on this connection. The datasheet contains the report's rows as a table, a summary report's with its groupings as their first columns, and is named after the report. A matrix or joined report is rejected."
},
"connectionId": {
"type": "string",
"examples": [
"c8e0a2b4-d6f8-4a0b-8c2d-4e6f8a0b2c4d"
],
"description": "The Salesforce connection the report is on: the `id` of a connection from `listConnections`. You must have access to the connection in Rollstack."
},
"connectionType": {
"type": "string",
"const": "Salesforce",
"description": "`Salesforce`. It must match the connection's `type` in `listConnections`."
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"spreadsheetId",
"sheetId",
"range"
],
"properties": {
"range": {
"type": "string",
"examples": [
"A1:F20"
],
"description": "The cells to read from the sheet, in A1 notation without the sheet's name, such as `A1:F20`, or `B2` for a single cell. The datasheet contains them as a table and is named after the range. Start the range at the header row so the columns take its names; without a header, they are named `Column 1`, `Column 2` and so on. Hidden rows and columns are left out, and whole columns such as `A:F` aren't accepted."
},
"sheetId": {
"type": "string",
"examples": [
"0"
],
"description": "The sheet the range is on: one of the `sheets[].id` values from `getSpreadsheet`. A sheet the file doesn't have is rejected."
},
"spreadsheetId": {
"type": "string",
"examples": [
"e6f8a0b2-c4d6-4e8f-9a0b-2c4d6e8f0a1b"
],
"description": "The Google Sheets or Excel file to read from: the `id` of a file from `searchSpreadsheets`. It must be a file you added in the app yourself."
}
},
"additionalProperties": false
}
]
},
"maxItems": 100,
"minItems": 1,
"description": "The data to add to the report, each source becoming one of its datasheets: an uploaded CSV file (`datasetId`), a dashboard tab (`connectionType`, `connectionId`, `dashboardId` and optionally `tabId`), a Salesforce report (`connectionType`, `connectionId` and `reportId`), or a range of a spreadsheet (`spreadsheetId`, `sheetId` and `range`). An uploaded file, a Salesforce report or a range comes in as a table, and a dashboard tab as a picture of the tab. If any source can't be added, none is. From 1 to 100 sources."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}getReportParameters — Get report parameters
A report's parameters, with which ones a burst can vary by, and the dashboard filters a parameter can link, with the parameter that already links each.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}createReportParameter — Create report parameter
Creates a parameter of a report, linked to the dashboard filters given, as the app's report parameters editor does. With a value, writes it into those filters and reads their datasheets again. Answers the parameter. Only the report's editors may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"name",
"filterIds"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Region"
],
"minLength": 1,
"description": "The parameter's name, as shown in Rollstack. It can't be the name of another parameter of the report."
},
"value": {
"anyOf": [
{
"anyOf": [
{
"type": "object",
"required": [
"type",
"values"
],
"properties": {
"type": {
"type": "string",
"const": "categorical"
},
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
}
},
"operator": {
"enum": [
"is",
"is_not",
"contains",
"doesnt_contain"
],
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"startDate",
"endDate"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"endDate": {
"type": "string"
},
"subtype": {
"type": "string",
"const": "date_range"
},
"startDate": {
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"rangeType",
"rangeN",
"periodType"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"rangeN": {
"type": "number"
},
"subtype": {
"type": "string",
"const": "date_relative"
},
"rangeType": {
"enum": [
"current",
"lastN",
"nextN"
],
"type": "string"
},
"periodType": {
"enum": [
"days",
"weeks",
"months",
"quarters",
"years",
"completeDays",
"completeWeeks",
"completeMonths",
"completeQuarters",
"completeYears"
],
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"month",
"year"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"year": {
"type": "number"
},
"month": {
"type": "number"
},
"subtype": {
"type": "string",
"const": "date_month_year"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"quarter",
"year"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"year": {
"type": "number"
},
"quarter": {
"type": "number"
},
"subtype": {
"type": "string",
"const": "date_quarter_year"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"date"
],
"properties": {
"date": {
"type": "string"
},
"type": {
"type": "string",
"const": "date"
},
"subtype": {
"type": "string",
"const": "date_single"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"subtype": {
"type": "string",
"const": "date_null"
}
}
},
{
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"const": "number"
},
"value": {
"type": "number"
}
}
},
{
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"const": "text"
},
"value": {
"type": "string",
"minLength": 1
}
}
}
]
},
{
"type": "null"
}
],
"default": null,
"description": "The parameter's value, of the `valueType` of the filters it links. When set, it is written into those filters and their datasheets are read again with it, so the report's slides change. If `null` or omitted, as for a parameter a burst's variants will set, the filters keep their own values. A value of a report parameter, in the shape of its type. Copy the shape of the parameter's `value` in `listBursts`, or of a variant's in `listBurstVariants`:\n\n- A list of values: `{ \"type\": \"categorical\", \"values\": [\"EMEA\"] }`, with at least one value. `operator` can also be `is_not`, `contains` or `doesnt_contain`; it is `is` when left out.\n- A number: `{ \"type\": \"number\", \"value\": 10 }`. Text: `{ \"type\": \"text\", \"value\": \"EMEA\" }`.\n- A date range: `{ \"type\": \"date\", \"subtype\": \"date_range\", \"startDate\": \"2026-01-01\", \"endDate\": \"2026-03-31\" }`. One date: `{ \"type\": \"date\", \"subtype\": \"date_single\", \"date\": \"2026-03-31\" }`.\n- A month or a quarter: `{ \"type\": \"date\", \"subtype\": \"date_month_year\", \"month\": 3, \"year\": 2026 }` (months 1 to 12), `{ \"type\": \"date\", \"subtype\": \"date_quarter_year\", \"quarter\": 1, \"year\": 2026 }`.\n- A relative period: `{ \"type\": \"date\", \"subtype\": \"date_relative\", \"rangeType\": \"lastN\", \"rangeN\": 3, \"periodType\": \"months\" }`. `rangeType` is `current`, `lastN` or `nextN`; `periodType` is `days`, `weeks`, `months`, `quarters` or `years`, or `completeDays` through `completeYears` for whole periods only."
},
"filterIds": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"maxItems": 200,
"description": "The filters the parameter links, by their `id` in `filters` from `getReportParameters`: its value is written into each, in every datasheet that reads its dashboard. Each must have no `parameterId` yet. A burst can vary by the parameter only if one of them has a `valueType`."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, by its `id` from `listReports` or `createReport`. Only reports whose `type` is `SlideDeck` work here: another type, such as a Google Slides presentation, returns `400`. You can also copy it from the report's link in Rollstack: it's the part right after `/slides/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}shareReport — Share report
Shares a report of any type with a member of the organization to view or edit it, or changes their permission. They get an email. A report that updates a file, such as a Google Slides presentation, also shares the file with them, as the app does.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"permission"
],
"properties": {
"permission": {
"enum": [
"view",
"comment",
"edit"
],
"type": "string",
"description": "What the member can do with the report. `view` lets them open, export and duplicate it. `comment` also lets them add, reply to and resolve comments on its slides. `edit` also lets them change its slides, data, schedules, email and other settings, run it, send its email, chat with the slides agent about it, and manage who it's shared with. Neither lets them delete the report or transfer its ownership. If the report is already shared with the member, this replaces their permission and they aren't notified again. On a report that updates a file in Google Drive or OneDrive, Rollstack also shares the file with them, as the app does."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id",
"userId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
},
"userId": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The member to share the report with, or to unshare it from. Use their `id` from `listMembers`, which only owners and admins can call, or their `userId` in `sharedWith` from `getReport` if the report is already shared with them. You can share a report only with active members of the organization, and not with yourself. Anyone the report is shared with can unshare it from themselves, even with `view` permission.",
"exclusiveMinimum": 0
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}unshareReport — Unshare report
Removes a user's share of a report of any type, and their access to its file when it updates one, as the app does.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id",
"userId"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
},
"userId": {
"type": "integer",
"maximum": 9007199254740991,
"description": "The member to share the report with, or to unshare it from. Use their `id` from `listMembers`, which only owners and admins can call, or their `userId` in `sharedWith` from `getReport` if the report is already shared with them. You can share a report only with active members of the organization, and not with yourself. Anyone the report is shared with can unshare it from themselves, even with `view` permission.",
"exclusiveMinimum": 0
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": true,
"destructiveHint": true
}getReportSchedules — List schedules
The schedules of a report of any type, with the syncs each updates and when each runs next, or null for one that never runs again. Read them before `updateReportSchedules`, which replaces them all.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}updateReportSchedules — Replace report schedules
Replaces the schedules of a report of any type, at most 10; an empty list removes them all. Only its editors may. A scheduled run updates the whole report: an AI update on a SlideDeck report, and a refresh of every sync on a report of another type, or only the `syncIds` a schedule names. Schedules are checked every 15 minutes, so a cron that fires more often still runs at most once per 15 minutes.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"schedules"
],
"properties": {
"schedules": {
"type": "array",
"items": {
"type": "object",
"required": [
"frequency",
"startDate",
"timezone"
],
"properties": {
"endDate": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"default": null,
"examples": [
"2027-11-02T09:00:00Z"
],
"description": "When the schedule ends: it never runs the report after this date and time. Omit it or pass `null` for a schedule that never ends. Like `startDate`, this is a local date and time in the schedule's `timezone`, written as if it were UTC. Must be later than `startDate`. Set it later than the last run you want: a run at exactly this time may be skipped."
},
"syncIds": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"maxItems": 500,
"minItems": 1
},
{
"type": "null"
}
],
"default": null,
"description": "The syncs, from `listReportSyncs`, that the schedule updates on a report other than a `SlideDeck`. `null` when it updates the whole report, which a slide deck always does. Omit it or pass `null` to update the whole report. Each id must be a sync of this report, so it only works on a report other than a `SlideDeck`. Keep the `syncIds` `getReportSchedules` returns for schedules you don't mean to change. A sync deleted later is skipped, so a schedule whose syncs are all gone updates nothing."
},
"timezone": {
"type": "string",
"examples": [
"America/New_York"
],
"minLength": 1,
"description": "The timezone the schedule runs in. Its run times (`cronExpression` or `selectedTimes`), `startDate` and `endDate` are all local times in this timezone, so a schedule set for 9:00 keeps running at 9:00 local time when daylight saving time starts or ends. Given as an IANA timezone name, such as `America/New_York`. UTC offsets such as `+05:30` aren't accepted."
},
"frequency": {
"enum": [
"hourly",
"daily",
"weekly",
"monthly",
"quarterly"
],
"type": "string",
"description": "How often the schedule runs. `hourly` runs every day at each time in `selectedTimes`, and takes no `cronExpression`. `daily`, `weekly`, `monthly` and `quarterly` run whenever `cronExpression` fires, and take no `selectedTimes`. For those, the frequency doesn't change when the report runs, but the app uses it to describe and edit the schedule, so pick the one that matches your cron expression."
},
"startDate": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"examples": [
"2026-11-02T09:00:00Z"
],
"description": "When the schedule starts: it never runs the report before this date and time. This is a local date and time in the schedule's `timezone`, written as if it were UTC: `2026-11-02T09:00:00Z` means 9:00 on November 2, 2026 in that timezone, not 9:00 UTC. For frequencies other than `hourly`, set it to the date and time of the first run: the app shows its time as the schedule's time, and when someone changes the schedule's frequency or days there, it rebuilds `cronExpression` at that time."
},
"selectedTimes": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):(00|15|30|45)$",
"examples": [
"09:00"
]
},
"maxItems": 96,
"minItems": 1,
"description": "The times of day an `hourly` schedule runs, every day, as 24-hour `HH:mm` in the schedule's `timezone`, such as `09:00` or `13:45`. Required for `hourly`; omit it for other frequencies. Each time must be on the quarter hour (`:00`, `:15`, `:30` or `:45`). From 1 to 96 times."
},
"cronExpression": {
"type": "string",
"examples": [
"0 9 * * 1"
],
"maxLength": 100,
"description": "When a `daily`, `weekly`, `monthly` or `quarterly` schedule runs: a five-field cron expression (minute, hour, day of month, month, day of week) in the schedule's `timezone`, such as `0 9 * * 1` for every Monday at 9:00, or `0 9 L * *` for 9:00 on the last day of each month. Required for those frequencies; omit it for `hourly`. Rollstack checks schedules every 15 minutes, so the minute field must include 0, 15, 30 or 45, and runs at other minutes are skipped. At most 100 characters."
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "The report's new schedules. They replace all of its current schedules, so read them with `getReportSchedules` first and include any you want to keep, with their `syncIds`; send an empty list to remove them all. When several schedules fall at the same time, the report runs once. Up to 10."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}getReportEmailConfig — Get email settings
Who a report's email goes to and how it is sent, for a report of any type. Answers 404 until its email is set up. On an older report that sends to several recipient groups, `to`, `cc`, `bcc` and `replyTo` list every group's addresses together.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}listReportEmails — List sent emails
The emails a report of any type sent, newest first: when, how, to whom, and whether each was delivered, failed or opened. Answers up to limit emails, 20 by default and 200 at most, and a nextCursor: pass it as cursor for the next page, until it is null.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 200,
"minimum": 1,
"description": "Maximum number of emails to return on this page, from 1 to 200. Defaults to `20`."
},
"cursor": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "Where to continue the list: pass the `nextCursor` returned with the previous page to get the next one. Omit it for the first page."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}updateReportEmailConfig — Replace email settings
Sets who a report's email goes to and how it is sent, for a report of any type, replacing the settings this endpoint covers; Drive sharing, attachment folders and the email's subject and body stay as set in the app. Only its editors may. The sender must be the user's own or shared with the organization. A report that sends to several recipient groups returns 400: change those in the app.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"to"
],
"properties": {
"cc": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"default": [],
"description": "The addresses to copy on the report's email, which every recipient can see. If omitted, no one is copied. Counts toward the 100 addresses allowed across `to`, `cc` and `bcc`."
},
"to": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"description": "The addresses to send the report's email to. If empty, no one receives it: the report's runs send no email and `sendReportEmail` returns 400. At most 100 addresses across `to`, `cc` and `bcc`."
},
"bcc": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"default": [],
"description": "The addresses to also send the report's email to without the other recipients seeing them. If omitted, no one is blind-copied. Counts toward the 100 addresses allowed across `to`, `cc` and `bcc`."
},
"replyTo": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"default": [],
"description": "The addresses recipients' replies should go to instead of the sender. They don't receive the email themselves. If omitted, replies go to the sender."
},
"trigger": {
"enum": [
"all",
"none",
"scheduled"
],
"type": "string",
"default": "all",
"description": "Which of the report's runs email it automatically. A run emails it when it updates everything, or when all its failures are in `ignoredFailureStatusMessages`. On a slide deck, `all` and `scheduled` work the same way: only runs started by its schedules (see `getReportSchedules`) send the email, and a slide deck with no datasheets is never emailed by its runs. On an older report, `all` emails after every run of the whole report, whether started by a schedule, with `startReportRun` or in the app, and `scheduled` only after runs its schedules start; a run of only some syncs never emails it. With `none` (Manual in the app), no run sends it: the email goes out only when sent with `sendReportEmail` or from the app. Defaults to `all`."
},
"smtpServerId": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"examples": [
"9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a"
],
"description": "The SMTP connection to send the report's email through, from `listSmtpConnections`; recipients see its `from` address as the sender. If `null` or omitted, the email is sent from Rollstack's own address. A connection `listSmtpConnections` doesn't list, or a Google or Microsoft account Rollstack can no longer send from, returns 403 unless it is already the report's sender."
},
"sharingFormat": {
"enum": [
"link",
"pdf",
"ppt",
"cloudLink"
],
"type": "string",
"description": "How the email delivers the report. `pdf` and `ppt` send it as a PDF or PowerPoint file, attached or behind a download button (see `sendAttachmentAsLink`); a slide deck leaves its hidden slides out. `link` sends a link to the Google Drive or OneDrive file an older report updates, shared with the recipients as set in the app; an email report sends its content in the email itself, and a slide deck has no such file, so one whose settings still contain `link` is emailed as a PDF behind a download button. `cloudLink` (Exported link in the app), for slide decks only, sends a link to the copy exported to Google Drive or OneDrive and shares it with the addresses in `to`, `cc` and `bcc` with the sharing permission set in the app, viewer unless changed there; if no permission is set, as after PDF or PPT was picked in the app, the copy isn't shared with them. `cloudLink` on an older report, `link` on a slide deck, or `ppt` on a Google Docs or Word report returns 400. For `cloudLink`, set up the export in the report's Update runs settings in the app first. If omitted, keeps the current format, or for a report whose email isn't set up yet, `pdf` on a slide deck and `link` on an older report."
},
"groupRecipients": {
"type": "boolean",
"default": true,
"description": "Whether to send one email to all the addresses in `to` together. Set it to `false` to send each address in `to` its own email with the same `cc`, `bcc` and `replyTo`; the addresses in `cc` and `bcc` then receive one copy per address in `to`. Defaults to `true`."
},
"sendAttachmentAsLink": {
"type": "boolean",
"description": "Whether the email puts the `pdf` or `ppt` file behind a Download PDF or Download PPT button instead of attaching it. When `false`, the file is attached. Has no effect with `cloudLink`. If omitted, keeps the current setting, or for a report whose email isn't set up yet, `true` on a slide deck and `false` on an older report."
},
"emailAnalyticsEnabled": {
"type": "boolean",
"default": false,
"description": "Whether to track when recipients open the report's email; opened emails show as Opened in the report's Email sends panel in the app. Setting it to `true` returns 403 unless email analytics is on for the organization (`emailAnalyticsEnabled` from `getOrganization`). Defaults to `false`."
},
"ignoredFailureStatusMessages": {
"type": "array",
"items": {
"enum": [
"tableau_view_not_found",
"dashboard_not_found",
"dashboard_tab_not_found",
"dashboard_not_ready",
"dashboard_has_errors",
"dashboard_invalid_layout",
"metabase_element_not_found",
"looker_element_not_found",
"element_not_found",
"google_slide_not_found",
"slide_not_found",
"file_not_found",
"sheet_not_found",
"sheet_hidden",
"range_not_found",
"duplicate_file_failed",
"merged_range_on_filter_range",
"insufficient_permissions",
"image_cropping_failed",
"visualization_not_found",
"visualization_not_ready",
"visualization_has_errors",
"visualization_empty",
"invalid_credentials",
"missing_credentials",
"instance_unavailable",
"column_not_found",
"empty_data",
"fetch_summary_data_error",
"fetch_visual_specification_error",
"incorrect_data_structure",
"missing_data",
"missing_formatted_value",
"malformed_data",
"viz_not_ready",
"worksheet_not_found",
"sync_not_found",
"file_update_failed",
"internal_server_error"
],
"type": "string"
},
"default": [
"slide_not_found"
],
"description": "The failures that shouldn't stop a run from emailing the report (see `trigger`). A run with failures still sends the email when all of them are in this list. On a slide deck, a run in which every datasheet fails never does. On a slide deck, include `internal_server_error` to email the report even when some of its datasheets fail. On an older report, include the `error.code` values from `listReportSyncs` to ignore. Defaults to `slide_not_found` alone, so by default a slide deck's run with any failed datasheet sends no email, and an older report's run still emails when only syncs on a missing slide fail.\n\nThe other values describe why a sync of an older report failed, and have an effect only on older reports:\n\n- `dashboard_not_found`, or the older `tableau_view_not_found`: the dashboard, Tableau workbook, Power BI report or spreadsheet could not be found.\n- `dashboard_tab_not_found`: the dashboard tab, Tableau view, Power BI report page or spreadsheet sheet could not be found.\n- `dashboard_not_ready`: the dashboard took too long to load.\n- `dashboard_has_errors`: the dashboard or spreadsheet failed to load because of an error in the tool it comes from.\n- `dashboard_invalid_layout`: the dashboard's layout is invalid, and it needs to be saved again.\n- `element_not_found`, or the older `metabase_element_not_found` and `looker_element_not_found`: the visualization could not be found.\n- `slide_not_found`, or the older `google_slide_not_found`: the slide that shows the visualization could not be found.\n- `file_not_found`: the spreadsheet file the visualization comes from could not be found.\n- `sheet_not_found`: the spreadsheet sheet could not be found.\n- `sheet_hidden`: the spreadsheet sheet is hidden and needs to be unhidden.\n- `range_not_found`: the spreadsheet range could not be found.\n- `duplicate_file_failed`: Rollstack could not prepare the spreadsheet file for the update.\n- `merged_range_on_filter_range`: the visualization has merged cells, which filters can't be applied to.\n- `insufficient_permissions`: the owner doesn't have edit access to the file.\n- `image_cropping_failed`: Rollstack could not crop the visualization's image.\n- `visualization_not_found`: the visualization could not be found in the dashboard.\n- `visualization_not_ready`: the visualization took too long to load.\n- `visualization_has_errors`: the visualization failed to load because of an error in the tool it comes from.\n- `visualization_empty`, or the older `empty_data`: the visualization is empty.\n- `invalid_credentials`: the connection's credentials are invalid.\n- `missing_credentials`: the connection's credentials were deleted, or the owner's access to it was suspended.\n- `instance_unavailable`: the data source's instance is temporarily unavailable.\n- `column_not_found`: a column the native chart uses is missing from its data.\n- `fetch_summary_data_error`, `fetch_visual_specification_error`, `missing_data`, `missing_formatted_value` and `viz_not_ready`: Rollstack could not fetch the data of a native chart.\n- `incorrect_data_structure`: the native chart's structure doesn't fit its data.\n- `malformed_data`: Rollstack could not fetch the data of a native chart or, from Snowflake or Databricks, the query is invalid.\n- `worksheet_not_found`: the Tableau worksheet could not be found.\n- `sync_not_found`: the visualization was deleted.\n- `file_update_failed`: the data was fetched but could not be written into the file."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}sendReportEmail — Send email
Emails a report to its recipients now, as it is. Only its editors may. Answers 400 when it has no recipients. An email report needs its email template set up in the app first. Sends in the background; while the user's send of the report is going, starts nothing. At most 5 sends a minute per user, test sends included.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}sendReportTestEmail — Send test email
Sends a report's email to the user only, and waits until it is sent. Only its editors may. Counts against the 5 sends a minute.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The report to act on, of any `type`, by its `id` from `listReports` or `createReport`. You can also copy it from the report's link in Rollstack (`appUrl`): it's the part right after `/slides/` or `/destinations/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": true,
"idempotentHint": false,
"destructiveHint": true
}listBursts — List bursts
The bursts of reports the user can see, newest first, with the report parameters their variants differ by and the template report they are copied from. You can filter by name, ignoring case. Answers up to limit bursts, 50 by default and 200 at most, and a nextCursor: pass it as cursor for the next page, until it is null. listReports leaves out the reports of a burst, its template and variants.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"query": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"regional"
],
"minLength": 1,
"description": "Only return bursts whose name contains this text, ignoring case: `region` matches `Regional Review`."
},
"limit": {
"type": "integer",
"default": 50,
"maximum": 200,
"minimum": 1,
"description": "Maximum number of bursts to return on this page, from 1 to 200. Defaults to `50`."
},
"cursor": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "Where to continue the list: pass the `nextCursor` returned with the previous page to get the next one. Omit it for the first page."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getBurstRun — Get burst run
Where the runs of a burst's variants stand, such as those startBurstRun started, with how each variant's latest run ended. Waits up to waitSeconds for none of them to be running and answers as soon as that happens, so call it again while the status is running. A run started in the app or by a schedule counts too.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"waitSeconds": {
"type": "integer",
"default": 20,
"maximum": 30,
"minimum": 0,
"description": "How long this call waits for the work to finish, in seconds: the message to the slides agent on `getReportMessage`, the run on `getReportRun`, the batch of variants being added on `getBurstVariantBatch`, the runs of a burst's variants on `getBurstRun`. It returns as soon as the work is done, or as things stand once the time is up, so call it again while `status` is still `queued` or `running`. `0` returns at once. Defaults to `20`; at most `30`."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}listBurstVariants — List burst variants
A burst's variants the user can open, oldest first, each with its values of the burst's parameters, how its latest run went, whether one is going, and who its email goes to. adding lists the variants the user is still adding. Answers up to limit variants, 50 by default and 200 at most, and a nextCursor: pass it as cursor for the next page, until it is null.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 50,
"maximum": 200,
"minimum": 1,
"description": "Maximum number of variants to return on this page, from 1 to 200. Defaults to `50`."
},
"cursor": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "Where to continue the list: pass the `nextCursor` returned with the previous page to get the next one. Omit it for the first page."
}
}
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getBurstVariantBatch — Get burst variant batch
A batch of variants being added to a burst, with where each variant stands: copied from the template report, then run once to fetch its data. Waits up to waitSeconds for the batch to end and answers as soon as it does, so call it again while the status is running. Your later batch on the burst reuses the id, so this describes the latest one.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"waitSeconds": {
"type": "integer",
"default": 20,
"maximum": 30,
"minimum": 0,
"description": "How long this call waits for the work to finish, in seconds: the message to the slides agent on `getReportMessage`, the run on `getReportRun`, the batch of variants being added on `getBurstVariantBatch`, the runs of a burst's variants on `getBurstRun`. It returns as soon as the work is done, or as things stand once the time is up, so call it again while `status` is still `queued` or `running`. `0` returns at once. Defaults to `20`; at most `30`."
}
}
},
"params": {
"type": "object",
"required": [
"id",
"batchId"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
},
"batchId": {
"type": "string",
"description": "The batch, by the `batchId` that `addBurstVariants` returned. A member's batches on a burst share one id, so it always refers to their latest."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}addBurstVariants — Add burst variants
Adds variants to a burst by their values of its report parameters: each is a copy of the template report that reads its datasheets with its own values, then runs once to fetch its data. Values are checked first, so a request with one the template's filters can't take adds nothing. Answers at once with the batch's batchId and the names the variants are added with: follow the batch with getBurstVariantBatch until it ends.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"variants"
],
"properties": {
"variants": {
"type": "array",
"items": {
"type": "object",
"required": [
"parameters"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"description": "The variant's name, which its report's name is built from as the burst's `variantNaming` says. If omitted, it is named after the values it sets, like `EMEA - Q1 2026`."
},
"parameters": {
"type": "object",
"examples": [
{
"5e7a9c1b-3d5f-4b7d-9e1a-3c5e7a9b1d3f": {
"type": "categorical",
"values": [
"EMEA"
]
}
}
],
"description": "The value the variant sets of each report parameter, by its `id` in the burst's `parameters`. A parameter left out keeps the template's value. A value must be one the template's datasheet filters can take, or the request returns 400 and adds nothing.",
"propertyNames": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"examples": [
"5e7a9c1b-3d5f-4b7d-9e1a-3c5e7a9b1d3f"
]
},
"additionalProperties": {
"anyOf": [
{
"type": "object",
"required": [
"type",
"values"
],
"properties": {
"type": {
"type": "string",
"const": "categorical"
},
"values": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
}
]
}
},
"operator": {
"enum": [
"is",
"is_not",
"contains",
"doesnt_contain"
],
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"startDate",
"endDate"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"endDate": {
"type": "string"
},
"subtype": {
"type": "string",
"const": "date_range"
},
"startDate": {
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"rangeType",
"rangeN",
"periodType"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"rangeN": {
"type": "number"
},
"subtype": {
"type": "string",
"const": "date_relative"
},
"rangeType": {
"enum": [
"current",
"lastN",
"nextN"
],
"type": "string"
},
"periodType": {
"enum": [
"days",
"weeks",
"months",
"quarters",
"years",
"completeDays",
"completeWeeks",
"completeMonths",
"completeQuarters",
"completeYears"
],
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"month",
"year"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"year": {
"type": "number"
},
"month": {
"type": "number"
},
"subtype": {
"type": "string",
"const": "date_month_year"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"quarter",
"year"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"year": {
"type": "number"
},
"quarter": {
"type": "number"
},
"subtype": {
"type": "string",
"const": "date_quarter_year"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype",
"date"
],
"properties": {
"date": {
"type": "string"
},
"type": {
"type": "string",
"const": "date"
},
"subtype": {
"type": "string",
"const": "date_single"
}
}
},
{
"type": "object",
"required": [
"type",
"subtype"
],
"properties": {
"type": {
"type": "string",
"const": "date"
},
"subtype": {
"type": "string",
"const": "date_null"
}
}
},
{
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"const": "number"
},
"value": {
"type": "number"
}
}
},
{
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"const": "text"
},
"value": {
"type": "string",
"minLength": 1
}
}
}
],
"description": "A value of a report parameter, in the shape of its type. Copy the shape of the parameter's `value` in `listBursts`, or of a variant's in `listBurstVariants`:\n\n- A list of values: `{ \"type\": \"categorical\", \"values\": [\"EMEA\"] }`, with at least one value. `operator` can also be `is_not`, `contains` or `doesnt_contain`; it is `is` when left out.\n- A number: `{ \"type\": \"number\", \"value\": 10 }`. Text: `{ \"type\": \"text\", \"value\": \"EMEA\" }`.\n- A date range: `{ \"type\": \"date\", \"subtype\": \"date_range\", \"startDate\": \"2026-01-01\", \"endDate\": \"2026-03-31\" }`. One date: `{ \"type\": \"date\", \"subtype\": \"date_single\", \"date\": \"2026-03-31\" }`.\n- A month or a quarter: `{ \"type\": \"date\", \"subtype\": \"date_month_year\", \"month\": 3, \"year\": 2026 }` (months 1 to 12), `{ \"type\": \"date\", \"subtype\": \"date_quarter_year\", \"quarter\": 1, \"year\": 2026 }`.\n- A relative period: `{ \"type\": \"date\", \"subtype\": \"date_relative\", \"rangeType\": \"lastN\", \"rangeN\": 3, \"periodType\": \"months\" }`. `rangeType` is `current`, `lastN` or `nextN`; `periodType` is `days`, `weeks`, `months`, `quarters` or `years`, or `completeDays` through `completeYears` for whole periods only."
}
}
},
"additionalProperties": false
},
"maxItems": 500,
"minItems": 1,
"description": "The variants to add, 1 to 500. Variants may hold the same values as one another or as an existing variant: each is added as its own report."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}createBurst — Create burst
Makes a report the template of a new burst whose variants differ by the report parameters given, and answers the burst, named after the report and with no variants yet. Add them with addBurstVariants. Only the report's editors may.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"templateReportId",
"parameterIds"
],
"properties": {
"parameterIds": {
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"examples": [
"5e7a9c1b-3d5f-4b7d-9e1a-3c5e7a9b1d3f"
]
},
"minItems": 1,
"description": "The template report's parameters the variants differ by, by their `id` from `getReportParameters`, in the order their values name a variant. Each must be `burstable` there. At least one."
},
"variantNaming": {
"enum": [
"sameName",
"prefix",
"suffix"
],
"type": "string",
"default": "suffix",
"description": "How each variant's report is named from the burst's name and the name the variant is added with, `EMEA` in a burst named `Regional Review`: `suffix` gives `Regional Review - EMEA`, `prefix` gives `EMEA - Regional Review`, and `sameName` gives `EMEA`. It applies to variants added from then on. Defaults to `suffix`."
},
"templateReportId": {
"type": "string",
"examples": [
"6c1f9a2e-3b4d-4e8f-9a1b-2c3d4e5f6a7b"
],
"description": "The report to make the template of the burst, by its `id` from `listReports`. You must be able to edit it, it must have datasheets, and it can't already be part of a burst. It becomes the template as it is: no copy is made."
}
},
"additionalProperties": false
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}startBurstRun — Run burst variants
Starts a run of every variant of a burst, or of the variants passed, as startReportRun does for each: it refreshes the variant's data and repairs its slides with AI. The template report isn't run; run it with startReportRun. Answers each variant's run at once: follow them all with getBurstRun until none is running, or one with getReportRun, passing the variant's id and runId. A variant already running answers that run and starts nothing.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"body": {
"type": "object",
"default": {},
"properties": {
"variantIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 500,
"minItems": 1,
"description": "The variants to run, by their `id` in `listBurstVariants`, instead of every variant, such as those whose last run failed. Each must be a variant of this burst. 1 to 500 ids."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": true
}updateBurstVariantRecipients — Set variant recipients
Sets who each variant's email goes to, replacing its to, cc and bcc. Its other email settings, such as its sender and which runs send it, stay as copied from the template; a variant without email settings gets the defaults. Sends no email. As in the app, the burst's owner and admins can set any variant's recipients, other members only those of variants they own or can edit; the others are skipped, as is a variant with several recipient groups, which the app asks to reconcile first.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"variants"
],
"properties": {
"variants": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"to"
],
"properties": {
"cc": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"default": [],
"description": "The addresses to copy on the variant's email, which every recipient can see. If omitted, no one is copied."
},
"id": {
"type": "string",
"description": "The variant, by its `id` in `listBurstVariants`."
},
"to": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"description": "The addresses to send the variant's email to. If empty, no one receives it. At most 100 addresses across `to`, `cc` and `bcc`."
},
"bcc": {
"type": "array",
"items": {
"type": "string",
"examples": [
"jane@acme.com"
]
},
"default": [],
"description": "The addresses to also send the variant's email to without the other recipients seeing them. If omitted, no one is blind-copied."
}
},
"additionalProperties": false
},
"maxItems": 500,
"minItems": 1,
"description": "The variants whose recipients to replace, 1 to 500. The other variants, and the rest of each variant's email settings, stay as they are."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}removeBurstVariants — Remove burst variants
Removes variants of a burst by their ids, and deletes their reports. Find the ids with listBurstVariants, which shows each variant's parameter values, and confirm them with the user. The user must be able to edit every variant passed, or nothing is removed: the burst's owner and admins can edit them all, other members only their own.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params",
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"variantIds"
],
"properties": {
"variantIds": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 500,
"minItems": 1,
"description": "The variants to remove, by their `id` in `listBurstVariants`, which shows each one's parameter values. Each must be a variant of this burst. 1 to 500 ids."
}
},
"additionalProperties": false
},
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The burst to act on, by its `id` from `listBursts`. You can also copy it from the burst's link in Rollstack: it's the part right after `/collections/`."
}
}
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": true
}listConnections — List connections
The data source connections the user can see, without their credentials: each one's type, name, settings such as its URL, owner, admins, default user and whether any user's access works.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}searchDashboards — Search dashboards
The dashboards of a Looker, Metabase, Omni, Lightdash, Sigma, Tableau or Power BI connection whose name holds any word of query or its singular, in any case, at most 50: those the most of the organization's reports read first, copies, old and personal ones last, then most words first, read with the user's access to the connection. A Tableau dashboard is a workbook, its views its tabs; a Power BI one a report, its pages its tabs; a Sigma one a workbook, its pages its tabs. On a Sigma connection, query can be a link to a workbook the user pasted: it finds only that workbook, with the page the link opens on as tabId, but not the link's control values, saved view or tag, and a link to another Sigma organization is rejected. On a Salesforce connection it finds reports the same way, the most recently run first among equals, each with its format: a report has no tabs, so add a tabular or summary one to a report with addReportDatasheets by its reportId, without getDashboard, and tell the user a matrix or joined one can't be added yet. Search by the name the user gives, confirm the dashboard with the user, then check its tabs and charts with getDashboard or add it to a report with addReportDatasheets. listConnections gives the connection's type and id.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"query": {
"type": "string",
"examples": [
"revenue"
],
"minLength": 1,
"description": "Words to search for in names, separated by spaces: a dashboard or spreadsheet is returned when its name contains any of them, case-insensitively. If omitted, results aren't filtered by name. At most 50 results are returned either way."
}
}
},
"params": {
"type": "object",
"required": [
"type",
"id"
],
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the connection, from `listConnections`, which also returns its `type`."
},
"type": {
"enum": [
"Looker",
"Metabase",
"Omni",
"Lightdash",
"Tableau",
"PowerBI",
"Sigma",
"Salesforce"
],
"type": "string",
"description": "The type of connection, as `type` in `listConnections`: the BI tool it connects to. Only Looker, Metabase, Omni, Lightdash, Sigma, Tableau and Power BI (`PowerBI`) connections have dashboards, and on a `Salesforce` connection the search finds its reports."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getDashboard — Get dashboard
A dashboard of a Looker, Metabase, Omni, Lightdash, Sigma, Tableau or Power BI connection, read with the user's access to the connection (a Salesforce report has no tabs or charts to read, so add it with addReportDatasheets directly): its tabs, and the charts and filters of the tab tabId names, one of the ids in tabs (else the one the dashboard opens on, a Power BI report's or Sigma workbook's first page). Tableau and Power BI list no charts or filters here: once the tab is added to a report, its charts are listed from its picture for the slides agent to add; a Sigma page lists its charts and tables, and the workbook's controls as its filters. Find the dashboard's id with searchDashboards. Confirm the dashboard and tab with the user, then add it to a report with addReportDatasheets; for another tab, call it again with that tab's id from tabs.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"query": {
"type": "object",
"properties": {
"tabId": {
"type": "string",
"examples": [
"12-overview"
],
"description": "The dashboard tab to read, by its `id` from the `tabs` that `getDashboard` returns: a Looker, Metabase or Lightdash tab, a Tableau view, a Power BI page or a Sigma page. If omitted, the dashboard's first tab is used, or the whole dashboard when it has no tabs, as on Omni. A tab the dashboard doesn't have returns a 404 error."
}
}
},
"params": {
"type": "object",
"required": [
"type",
"id",
"dashboardId"
],
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the connection, from `listConnections`, which also returns its `type`."
},
"type": {
"enum": [
"Looker",
"Metabase",
"Omni",
"Lightdash",
"Tableau",
"PowerBI",
"Sigma"
],
"type": "string",
"description": "The type of connection, as `type` in `listConnections`: the BI tool it connects to. Only Looker, Metabase, Omni, Lightdash, Sigma, Tableau and Power BI (`PowerBI`) connections have dashboards."
},
"dashboardId": {
"type": "string",
"description": "The dashboard to read, by the `id` that `searchDashboards` returns."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}searchSpreadsheets — Search spreadsheets
The Google Sheets and Excel files the user added in the app whose name holds any word of query, in any case, most words first, at most 50. Rollstack can't search the user's whole Google Drive or OneDrive: for another file, ask the user to add it in the app. Confirm the file with the user, then list its sheets with getSpreadsheet.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"query": {
"type": "object",
"properties": {
"query": {
"type": "string",
"examples": [
"revenue"
],
"minLength": 1,
"description": "Words to search for in names, separated by spaces: a dashboard or spreadsheet is returned when its name contains any of them, case-insensitively. If omitted, results aren't filtered by name. At most 50 results are returned either way."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}getSpreadsheet — Get spreadsheet
A Google Sheets or Excel file the user added in the app, with its sheets, read with the user's own Google or Microsoft account. Fails with user-missing-oauth when the user hasn't connected that account in the app. Find the file's id with searchSpreadsheets, then add a range of one of its sheets to a report with addReportDatasheets by the sheet's id.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The spreadsheet whose sheets to list, by its `id` from `searchSpreadsheets`. This is Rollstack's identifier, not the file's id in Google Drive, OneDrive or SharePoint. It must be one of your own spreadsheets in Rollstack: another member's spreadsheet returns `404`, as does an Excel file stored in Google Drive."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}listSmtpConnections — List SMTP connections
The user's SMTP connections and the ones shared with the organization, without their credentials.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}listFolders — List folders
The folders the user can see, each with its parent, null at the top level, and the user's permission on it: null, view, edit or manage. Pass a folder's id as folderId to listReports or createReport.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}submitFeedback — Send feedback
Tells the Rollstack team about something the user asked for that you couldn't do: a tool or endpoint that is missing, a call that was refused or failed, or a task nothing covers. Send it only after the user agrees: tell them what you couldn't do, offer to report it, and show what you'd send. The team reads every message to decide what to build next; it doesn't answer, and it doesn't fix the problem for the user.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"body"
],
"properties": {
"body": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string",
"examples": [
"The user asked to duplicate their Q3 report for Q4. No tool copies a report, so I could only create an empty one with createReport."
],
"maxLength": 4000,
"minLength": 1,
"description": "What the user wanted, what you tried, and what was missing or blocked you, in a few sentences. Name the tools you called and the errors they answered. Leave out credentials and personal data."
},
"operationId": {
"type": "string",
"examples": [
"sendReportMessage"
],
"maxLength": 200,
"description": "The tool or operation that refused, failed or fell short, if one did."
}
},
"additionalProperties": false
},
"idempotencyKey": {
"type": "string",
"pattern": "^[\\x20-\\x7e]{1,255}$",
"description": "A unique value, such as a UUID, that makes retrying this call safe. A retry with the same key within 24 hours answers the first call's result instead of running it again. Use a new key for each new call. From 1 to 255 printable ASCII characters."
}
}
}{
"readOnlyHint": false,
"openWorldHint": false,
"idempotentHint": false,
"destructiveHint": false
}listMembers — List members
The members of the organization, with their role, authentication role, insights access and whether they are active. Optionally only those with a status, active or deactivated, or with an email.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"query": {
"type": "object",
"properties": {
"email": {
"type": "string",
"examples": [
"jane@acme.com"
],
"description": "Only return the member with exactly this email address, ignoring case. Returns an empty list if no member has it, or if they don't match `status`."
},
"status": {
"enum": [
"active",
"deactivated"
],
"type": "string",
"description": "Only return `active` members, or only `deactivated` ones. If omitted, returns both."
}
}
}
}
}{
"readOnlyHint": true,
"openWorldHint": false,
"idempotentHint": true,
"destructiveHint": false
}Prompts
3 advertised
build-deck-from-dashboards — Build a deck from dashboards
Builds a new Rollstack slide deck from your BI dashboards, in your company template.
- topic
- What the deck covers, such as "Q3 business review" (required)
- dashboards
- The dashboards to build it from, by name. Leave empty to pick them together
refresh-and-email-report — Refresh and email a report
Updates a report with fresh data from its sources, shows you what changed, then emails it once you've checked it.
- report
- The report's name (required)
why-did-my-report-fail — Why did my report fail?
Finds a report's latest failed update, explains what went wrong and suggests a fix.
- report
- The report's name (required)
Resources
2 advertised
Report viewer
Shows the slides of a Rollstack report
ui://rollstack/report-viewer-images-v3.htmlTemplate picker
Shows the company's Rollstack templates to pick one
ui://rollstack/template-picker-v1.html30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 1087 ms
- 95th percentile latency
- 1087 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 1087 ms · metadata changed · 59 tool(s), 2 resource(s), 3 prompt(s); warnings: Advertises resources/templates/list but does not implement it
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http rollstack-mcp https://api.rollstack.com/public/v1/mcpCodex
codex mcp add rollstack-mcp --url https://api.rollstack.com/public/v1/mcpCursor
{
"mcpServers": {
"rollstack-mcp": {
"url": "https://api.rollstack.com/public/v1/mcp"
}
}
}Cline
{
"mcpServers": {
"rollstack-mcp": {
"type": "streamableHttp",
"url": "https://api.rollstack.com/public/v1/mcp",
"disabled": false
}
}
}VS Code
{
"servers": {
"rollstack-mcp": {
"type": "http",
"url": "https://api.rollstack.com/public/v1/mcp"
}
}
}Gemini CLI
gemini mcp add --transport http rollstack-mcp https://api.rollstack.com/public/v1/mcpClaude Desktop
https://api.rollstack.com/public/v1/mcpWindsurf
{
"mcpServers": {
"rollstack-mcp": {
"serverUrl": "https://api.rollstack.com/public/v1/mcp"
}
}
}Let your agent find its tools
Find servers like Rollstack MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.
Other productivity and knowledge servers
Do you run Rollstack MCP?
Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.