Skip to content

API reference

Every skills route — listing, generation, the editable head, published versions, and the SKILL.md download.

Paths below are given on the cassette’s own listener. Through tapes, replace /api/skills with /v1/cassettes/skills.

Route Purpose
GET /api/skills Paginated list, with search, scopes and sort
POST /api/skills Create a skill authored from scratch
POST /api/skills/generate Generate a skill from nominated sessions
GET /api/skills/{id} Read one skill
PUT /api/skills/{id} Update the editable head
DELETE /api/skills/{id} Delete, history included
GET /api/skills/{id}/skill.md Download the SKILL.md
GET /api/skills/{id}/versions Published history
POST /api/skills/{id}/versions Publish a version snapshot
POST /api/skills/{id}/duplicate Fork under a fresh id

GET /api/skills

Parameter Meaning
limit Page size. Default 24, max 100.
cursor Opaque keyset cursor from a previous next_cursor.
q Search over name, description and tags.
scope Which slice: all, mine, or team.
sort downloads for most-downloaded; defaults to most recently updated.
session_id Return only skills generated from this session. Unpaginated.

Pagination mirrors the tapes read API: pass the returned next_cursor to continue, and its absence means the last page. Reset the cursor when changing sort — a keyset cursor encodes a position in one ordering and means nothing in another.

session_id switches modes rather than filtering: it answers “what came out of this session?” and returns the whole answer without paging.

400 on a malformed cursor, 500 on a listing failure.

POST /api/skills/generate

Takes the session ids to learn from and generates a skill with the configured LLM.

Code When
201 The generated skill.
400 Invalid body, or sessionIds missing or empty.
404 One or more source sessions were not found.
422 The sources carried nothing the generator could use, or no LLM key is configured.
500 Generation or persistence failed.
501 No core URL is configured, so transcripts cannot be read at all.

The distinction between 404, 422 and 501 is the useful one. 404 means the sessions do not exist; 422 means they do but yielded nothing worth a skill (or the provider is unusable); 501 means this cassette was never told where tapes is. Only the last is a deployment error — see Deploying.

POST /api/skills creates one from scratch: 201, or 400 on an invalid body.

GET /api/skills/{id} reads one: 200, or 404.

PUT /api/skills/{id} updates the head: 200, 400 on an invalid body, 404.

DELETE /api/skills/{id} deletes the skill and its history: 204, 404, and 403 when the skill has a creator and the caller is not that creator. A skill with no recorded author is unattributed and deletable by anyone.

Delete is the only route that checks the caller. In particular PUT does not: any caller may edit any skill, including one attributed to someone else. If that matters for your deployment, the control has to live in front of this cassette.

POST /api/skills/{id}/duplicate forks under a fresh id: 201, or 404.

GET /api/skills/{id}/versions lists the published history: 200, 500.

POST /api/skills/{id}/versions publishes an immutable snapshot: 201, 404, or 500. The version row and the head bump land together, so a publish never leaves a durable snapshot behind a stale head.

A 500 is not proof that nothing landed, though: a commit whose acknowledgement is lost reports as a failure while having persisted. Read GET /api/skills/{id}/versions before retrying — a blind retry publishes a second version rather than repeating the first, because each retry takes the next version number.

Concurrent publishes racing for the same number are resolved internally and do not surface as errors.

GET /api/skills/{id}/skill.md returns text/markdown — the drop-in document. 200 or 404.

This route counts a download, which is what sort=downloads ranks. Anything polling it inflates that ordering.