---
title: "Pin a dashboard panel to the caller's Home."
method: POST
path: "/v1/me/home-pins"
tags: ["dashboards"]
---

# Pin a dashboard panel to the caller's Home.

`POST /v1/me/home-pins`

## Request

- Base URL: `http://localhost:8080`
- URL: `http://localhost:8080/v1/me/home-pins`
- Auth: one of:
  - API key in cookie `dvt_session`
  - HTTP bearer

Pins a panel (idempotent upsert on dashboard + page + panel). Requires the dashboard
read capability AND per-dashboard read access; an unknown dashboard, a dashboard the
caller cannot read, or a panel not in the dashboard's spec all 404. Body is at most
16 KiB; unknown fields are rejected. `filterState` has at most 32 keys; each value
must be a `v1:`-encoded string of at most 2048 characters. 201 when newly pinned,
200 when an existing pin's filter state was updated. At most 48 pins per user (409).

## Request body

- HomePinCreate
  - `dashboardId` string, uuid, required
  - `pageId` string: Page id; empty/omitted for a single-page dashboard.
  - `panelId` string, required
  - `filterState` object: Saved filter state, param name to a `v1:`-encoded value.

## Response `200`

Existing pin updated.

- HomePinEnvelope
  - `data` HomePin, required
    - `id` string, uuid, required
    - `dashboardId` string, uuid, required
    - `pageId` string, required
    - `panelId` string, required
    - `filterState` object, required
    - `createdAt` string, date-time, required
    - `accessible` boolean, required: Whether the dashboard still exists and the caller can read it (re-checked per request).
    - `dashboardTitle` string: Present only when `accessible` 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

- `201`: Pinned.
- `400`: Malformed request.
- `401`: Missing, invalid, or expired session.
- `403`: The caller's role does not permit this action.
- `404`: Resource does not exist.
- `409`: The request conflicts with the current state of the resource.

---

[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)
