---
title: "Grant a user access to a dashboard."
method: POST
path: "/v1/dashboards/{id}/acl"
tags: ["dashboards"]
---

# Grant a user access to a dashboard.

`POST /v1/dashboards/{id}/acl`

## Request

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

Upserts a direct user ACL grant on the dashboard (DVT-665). If the user already has a
grant, the role is updated. Only user principals are supported; the `principalId` must be
an active member of the organization. Roles: `viewer`, `editor`, or `admin` (`owner` is
assigned at creation and cannot be granted via ACL). Requires share:manage on the
dashboard (owner / org admin / acl-admin).
In the Snowflake native app, ownership and acl-admin grants are ignored for callers whose live tier is viewer.

## Request body

- GrantDashboardRequest: Request body for POST /v1/dashboards/{id}/acl.
  - `principalType` 'user', required: Only "user" is supported.
  - `principalId` string, uuid, required: The user to grant access to. Must be an active member of the org.
  - `role` 'viewer' | 'editor' | 'admin', required: The role to grant. "owner" cannot be granted via ACL.

## Response `201`

Grant created or updated.

- object
  - `data` DashboardGrant, required: A user ACL grant surfaced on a dashboard — either a direct grant on the dashboard itself, or (DVT-1421) a grant inherited from one of the dashboard's ancestor folders. GET /v1/dashboards/{id}/acl returns direct grants first, then inherited ones; a user with both a direct and an inherited grant appears as two rows. The `inherited`/`viaFolderId`/`viaFolderName` fields are present ONLY on folder-inherited rows.
    - `userId` string, uuid, required: The grantee's user ID.
    - `email` string, email: The grantee's email address.
    - `displayName` string: The grantee's display name.
    - `role` 'viewer' | 'editor' | 'admin', required: The granted role.
    - `inherited` boolean: True when this grant comes from a shared ancestor folder rather than being granted directly on the dashboard (DVT-1421). Absent (falsy) on direct grants.
    - `viaFolderId` string, uuid: The ancestor folder that contributed this grant. Present only when `inherited` is true.
    - `viaFolderName` string: The contributing folder's name, for display. Present only when `inherited` is true.
  - `meta` Meta, required: Response metadata.
    - `requestId` string, required: Correlates with the X-Request-Id header.
    - `total` integer: Item count, present on collection responses.
    - `nextCursor` string, nullable: Opaque keyset-pagination cursor, present on paginated responses (e.g. GET /v1/dashboards) when more rows exist beyond this page. Pass it back as the `cursor` query param to fetch the next page; absent or null on the last page.
    - `roleResolveDegraded` boolean: Snowflake mode only (DVT-2260), on GET /v1/dashboards: present and true when the caller's live Snowflake role resolution failed or was unavailable — role-shared dashboards may be missing from this page. Omitted (not merely false) whenever resolution succeeded or the role-share arm does not apply (off snowflake mode, an org admin/owner, or off the ingress listener).

## Other responses

- `400`: Malformed request.
- `401`: Missing, invalid, or expired session.
- `403`: The caller's role does not permit this action.
- `404`: Resource does not exist.

---

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