---
title: "List skills readable by the caller."
method: GET
path: "/v1/skills"
tags: ["skills"]
---

# List skills readable by the caller.

`GET /v1/skills`

## Request

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

Returns up to 200 of the org skills the caller can read (ADR-0061), newest-updated first: every `public` skill in the caller's org, plus any `private`/`shared` skill the caller owns or has an ACL grant on. Org-scoped and tenant-isolated (ADR-0025) — never returns another org's skills. The `data` array is always present (never null). Requires `skill:read`.

With `serve=true`, returns the caller's SERVABLE set (owner + public + ACL) even for an org admin/owner — the admin-sees-all management view is suppressed. This is the resolution the engine MCP serve path (`dvt://skill/org/{slug}`) enumerates from, so an admin's agent session never lists other members' private skills. Omit it (the default) for the management view, where an admin/owner sees every skill in the org.

## Query parameters

- `serve` boolean

## Response `200`

A collection of skills.

- object
  - `data` Skill[], required
    - `id` string, uuid, required
    - `folderId` string, uuid, nullable, required: The containing library folder, or null when unfoldered (DVT-1563). Set via PUT /v1/skills/{id}/folder. Only the skill's owner (or an org admin/owner) may move it between folders. Independent of sectionId — folders are a library-navigation grouping, sections are the curated-doc taxonomy (skill_sections); moving between one never touches the other.
    - `ownerId` string, uuid, required: The user who created the skill.
    - `name` string, required
    - `slug` string, required: Org-unique URL segment that drives the MCP resource URI `dvt://skill/org/{slug}`. Derived from `name` at create time when omitted; stable across renames. Constrained to lowercase alphanumerics + hyphen (no `/`, `.`, `%`) so it cannot traverse out of the `org/` MCP namespace and shadow the canonical `dvt://skill/spec-authoring` resource (ADR-0061 §3; security review). Enforced on both caller-supplied and name-derived slugs.
    - `sectionId` string, uuid, nullable: Optional admin-curated grouping (DVT-943 M3) — an id from GET /v1/skill-sections. Omitted/null when the skill is unsectioned. Cleared automatically when its section is deleted.
    - `description` string, required: What this skill is (metadata field 1 of 4).
    - `whenToUse` string, required: When an agent should apply it (metadata field 2 of 4).
    - `whoFor` string, required: Who it's for (metadata field 3 of 4).
    - `howToApply` string, required: How an agent should apply it (metadata field 4 of 4).
    - `body` string, required: The skill body — markdown, served verbatim over MCP. Length-capped to bound the served prompt-injection + unbounded-markdown DoS surface (ADR-0061 §5).
    - `visibility` 'private' | 'shared' | 'public', required: 'public' = org-wide skill (served to every member); 'private'/'shared' = personal (owner + ACL grantees).
    - `version` integer, required: Optimistic-concurrency version. Pass this back on PATCH.
    - `schemaVersion` integer, required
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
  - `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

- `401`: Missing, invalid, or expired session.
- `403`: The caller's role does not permit this action.

---

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