> For clean Markdown of any page, append `.md` to the page URL.
> For a complete documentation index, see https://docs.sarvam.ai/llms.txt.
> For full documentation content in one file, see https://docs.sarvam.ai/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server.

# Boards API overview

A **board** is a custom analytics dashboard: a set of SQL-backed widgets, grouped into tabs, parameterised by filters your team can change without editing the query. This API does everything the dashboard does — discover the schema, develop a query, save it as a widget, run it, and schedule recurring delivery of the result.

For the dashboard walkthrough of the same concepts, see [Boards](/conversations/monitor/boards) under Monitor.

## Base URL

```
https://apps.sarvam.ai/api/analytics/v1/{org_id}/{workspace_id}
```

Boards are **workspace-scoped**: board paths carry no `app_id`, and a board can query across every agent in the workspace.

Requests are authenticated with your API key, as everywhere else in the Voice Agents API — see [Introduction](/conversations/api/introduction).

## Rate limits

Two independent limits apply, and a request must satisfy both.

| Limit                    | Scope                                    | Applies to                      |
| ------------------------ | ---------------------------------------- | ------------------------------- |
| **60 requests / minute** | Per API key, within an org and workspace | Every boards endpoint           |
| **20 requests / minute** | Per organization                         | `POST /query-preview`           |
| **20 requests / minute** | Per organization                         | `POST /widgets/{widget_id}/run` |
| **50 requests / minute** | Per organization                         | `POST /tabs/{tab_id}/run`       |

The per-organization limits are shared across every key and every user in the org — a colleague running queries in the dashboard consumes the same budget as your integration.

Exceeding either returns `429` with a `Retry-After` header giving the window in seconds:

```
HTTP/1.1 429 Too Many Requests
Retry-After: 60
```

Honour `Retry-After` rather than retrying immediately, and back off exponentially if you see repeated `429`s. If your workload needs more headroom, higher limits can be provisioned per organization — contact Sarvam support.

## How the pieces fit together

#### Discover the schema

[Get query schema](/conversations/api/boards/query/schema) returns the tables and columns available to board SQL, with their types. Start here — it is the authoritative list, and querying anything outside it fails.

#### Develop the query

[Preview query](/conversations/api/boards/query/preview) runs ad-hoc SQL and returns rows without saving anything.

#### Save it as a widget

[Create board](/conversations/api/boards/create), then [Create widget](/conversations/api/boards/widgets/create) with your SQL, a visualization type, and the filters its `{{tokens}}` declare.

#### Run it

[Run widget](/conversations/api/boards/widgets/run) for one result, or [Run tab](/conversations/api/boards/tabs/run) for every widget on a tab in a single call.

#### Have it delivered

[Create notification rule](/conversations/api/boards/notifications/create) emails or Slacks a widget's result on a cron schedule.

Filters are never created directly — that is why [List filters](/conversations/api/boards/filters/list) and [Update filter](/conversations/api/boards/filters/update) exist but "create filter" does not. A filter comes into being when a `{{token}}` appears in a widget's SQL, and the board's filter set is the union of the tokens across its widgets. See [Writing board SQL](/conversations/api/boards/sql#filter-tokens).

## Errors

Every error carries a `detail` field. For most failures it is a message string:

```json
{ "detail": "No such board in this workspace" }
```

For SQL and query-execution failures it is an object with a machine-readable `code`, so you can branch on the cause rather than parsing prose:

```json
{ "detail": { "code": "FORBIDDEN_TABLE", "message": "Table `users` is not available." } }
```

The full code table is on [Writing board SQL](/conversations/api/boards/sql).

## What this API does not do

These are deliberate, not gaps to work around:

* **No deletion.** There are no `DELETE` routes. Boards, tabs, widgets, and notification rules are created and edited through the API but removed only in the dashboard.
* **No CSV export.** Widget downloads are a dashboard feature. Read results as JSON from the run endpoints.
* **No whole-board run.** The tab is the unit — call [Run tab](/conversations/api/boards/tabs/run) once per tab.
* **No AI query generation.** Generating SQL from a plain-language prompt is dashboard-only.

## Next

#### [Writing board SQL](/conversations/api/boards/sql)

Which tables you can query, filter tokens, and every error code.

#### [Best practices](/conversations/api/boards/best-practices)

Choosing between preview, widget run, and tab run — plus caching and polling.