---
title: "List Skills"
method: GET
path: "/skills"
tags: ["SKILLS"]
---

# List Skills

`GET /skills`

One page of the skills visible to the caller. Postgres only — no S3 reads.

Paginated from the start rather than added later: the visibility filter also
matches every tenant-wide skill, so this response grows with the tenant's
shared library, and changing the envelope once clients depend on it is a
breaking change.

``page``/``size`` are not declared here on purpose — ``add_pagination(app)``
(``main.py``) supplies them, so this endpoint inherits the same defaults and
ceilings as every other paginated route instead of hard-coding its own. The
LIMIT/OFFSET and the COUNT run in SQL; ``_summary`` is applied to the page
rows only.

Both filters exist because the client cannot do them correctly. Narrowing a
*page* is not narrowing the *set*: the Skills page's scope tabs filtered the
50 rows they had been handed, so a tab could report "no skills" while
matching skills sat on page 2. Anything a paginated list is filtered by has
to be filtered in SQL.

``datamate_id`` answers "what does this workspace have?", which nothing could
ask before — attachments were only readable from the skill's side, on the
detail response, one request and one S3 read at a time.

Note the two filters are asymmetric on purpose. ``privacy`` needs no
authorization: it only ever narrows what the visibility filter already
allows. ``datamate_id`` names another object, so the workspace is checked
first — see below.

## Query parameters

- `privacy` 'public' | 'private'
- `datamate_id` integer, nullable — Restrict to skills attached to this workspace.
- `page` integer — Page number
- `size` integer — Page size

## Response `200`

Successful Response

- PageCustomSkillSummary
  - `items` CustomSkillSummary[], required
    - `public_id` string, required
    - `name` string, required
    - `description` string, nullable
    - `privacy` 'public' | 'private'
    - `file_count` integer
    - `source_ref` SkillSourceRef — Where an imported skill was copied from. Present only on skills imported from the public catalog; ``None`` means the skill was uploaded or written by hand. Carried on the list payload so the Skills table can attribute a row to its upstream origin without a second request, and so a renamed copy can still be traced back.
      - `repo` string, required
      - `path` string, required
      - `commit_sha` string, required
      - `imported_at` string, nullable
    - `created_by` integer, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
  - `total` integer, nullable, required
  - `page` integer, nullable, required
  - `size` integer, nullable, required
  - `pages` integer, nullable

## Other responses

- `422` — Validation Error

## Changes

- **2026-09-02** `fcb62c79da95` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/myaltimate/apis/fastapi/changes/skills/get.md)

---

[API](https://skmtc.dev/myaltimate/apis/fastapi.md) · [All operations](https://skmtc.dev/myaltimate/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/myaltimate/fastapi/revisions/fcb62c79da95/schema)
