---
name: seren-skills
description: "Create, manage, update, sell, and download Seren agent skills through /publishers/seren-skills."
---

# Seren Skills

Use this skill when the user wants to discover, author, publish, sell, or maintain Seren agent skills.

## API

Use this skill alongside the core Seren API skill (`https://api.serendb.com/skill.md`).

## Base Route

All routes go through `https://api.serendb.com/publishers/seren-skills`.

## Authentication

Authenticated routes require `Authorization: Bearer $SEREN_API_KEY`. Public discovery routes can be called without authentication when the skill itself is public and published. Seren Core proxies authenticated requests to this publisher and injects `X-Seren-User-Id` plus `X-Seren-Organization-Id` headers.

## Skill Model

A skill is stored as versioned `SKILL.md` plus a manifest. `slug` is the public identifier used in URLs; `skill_folder_name` is the folder name used when the service forward-publishes the skill to the canonical GitHub repository. Visibility controls access:

- `public`: discoverable and downloadable when published.
- `private`: visible only to owners and collaborators.
- `paid`: discoverable, but download requires a grant from purchase or ownership.

## Versioning And Conflicts

Use `expected_current_version_id` when creating versions or accepting update requests. If the base is stale, the service materializes a draft and merge state instead of overwriting another version. Reverse-sync from GitHub also runs conflict detection against open update requests and drafts.

## GitHub Publishing

For eligible public skills, version writes enqueue a forward-publish job that commits `<folder>/<skill>/SKILL.md` to the canonical GitHub repository. The GitHub status endpoints expose ledger state and retry controls. If GitHub App credentials are not configured, jobs idle until operators provision them.

## Usage Billing

Private skill creation, private skill storage days, and private skill sync/download activity are recorded as durable usage events. A background worker settles pending events through Seren Core billing using event UUIDs as idempotency keys.

## Pagination

`GET /skills` is **paginated** (default `limit=50`, max `100`). The response envelope is:

```json
{
  "data": [...],
  "pagination": {
    "total": 140,
    "count": 50,
    "limit": 50,
    "offset": 0,
    "has_more": true
  }
}
```

Do not treat the returned `data` array as the full catalog. Loop until `pagination.has_more` is `false`, advancing `offset` by `pagination.count`:

```bash
OFFSET=0
while :; do
  RESP=$(curl -sS "https://api.serendb.com/publishers/seren-skills/skills?limit=100&offset=$OFFSET")
  echo "$RESP" | jq -c '.data[]'
  HAS_MORE=$(echo "$RESP" | jq -r '.pagination.has_more')
  [ "$HAS_MORE" = "true" ] || break
  COUNT=$(echo "$RESP" | jq -r '.pagination.count')
  OFFSET=$((OFFSET + COUNT))
done
```

The same top-level `{ data, pagination }` shape is used for paginated JSON responses across Seren publishers.

## Known Gotchas

1. **Use stable slugs.** Slugs identify skills in URLs and GitHub paths.
2. **Paid skills require `price_cents > 0`.** Creation rejects paid visibility without a positive price.
3. **Downloads can be public or gated.** Public published skills can be downloaded anonymously; private and paid skills require identity and access.
4. **Update requests do not automatically merge on conflict.** Use draft and merge-state endpoints to resolve conflict materialization.
5. **Git identity matters.** Set `/git-identity` before publishing if commits should carry a specific co-author identity.
6. **Organization folders are operational metadata.** They map organizations to canonical GitHub folder slugs and should be set before organization-owned publishing.
7. **`GET /skills` is paginated; do not trust the array length as the catalog size.** Default `limit` is 50, max is 100. Use `pagination.has_more` and advance `offset` by `pagination.count`. See the Pagination section above.

## Discovery

Find public skills, inspect metadata, and download accessible skill bundles.

Get publisher metadata and top-level route hints.

### GET `/`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/"
```

Fetch this canonical skill document.

### GET `/skill.md`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skill.md"
```

List public skills. **Paginated** (default `limit=50`, max `100`). Inspect `pagination.has_more` to consume the full catalog; do not treat the returned `data` array as the full set. Authenticated callers can use `mine=true` for their own skills.

### GET `/skills`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills"
```

Get skill details when the skill is public or the caller has access.

### GET `/skills/{slug}`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG"
```

Download the current skill bundle when the caller can download it.

### GET `/skills/{slug}/download`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/download"
```

Download the bundle manifest (metadata + per-file metadata, no file bodies) for installing large bundles in pieces.

### GET `/skills/{slug}/download/manifest`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/download/manifest"
```

Download one bundle file body by path; pair with the manifest to fetch large bundles under the gateway response cap.

### GET `/skills/{slug}/download/file`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/download/file?path=<path>"
```

## Authoring

Create skills, edit metadata, manage visibility, and publish new content.

Create a user- or organization-owned skill with initial SKILL.md content.

### POST `/skills`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills" \
  -H "Content-Type: application/json" \
  -d '{"description":"","name":"my-agent","slug":"my-publisher","visibility":""}'
```

Update skill metadata, visibility, discoverability, price, and other settings.

### PATCH `/skills/{slug}`

```bash
curl -sS -X PATCH "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG" \
  -H "Content-Type: application/json" \
  -d '{"description":"","discoverability":null,"folder_slug":"my-publisher"}'
```

Delete a skill owned or managed by the caller.

### DELETE `/skills/{slug}`

```bash
curl -sS -X DELETE "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG"
```

Load the editable ProseMirror document for a skill.

### GET `/skills/{slug}/edit`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/edit"
```

List every file in the current bundle (SKILL.md + bundle entries).

### GET `/skills/{slug}/files`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/files"
```

Fetch one file's bytes from the current bundle.

### GET `/skills/{slug}/files/{path}`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/files/<path>"
```

Replace or add one file. Synthesises a `file-edit-<hash>` version label and short-circuits no-op edits.

### PUT `/skills/{slug}/files/{path}`

```bash
curl -sS -X PUT "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/files/<path>" \
  -H "Content-Type: application/json" \
  -d '{"content_b64":"","expected_current_version_id":"<expected_current_version_uuid>"}'
```

Drop one file from the bundle. SKILL.md cannot be deleted.

### DELETE `/skills/{slug}/files/{path}`

```bash
curl -sS -X DELETE "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/files/<path>" \
  -H "Content-Type: application/json" \
  -d '{"expected_current_version_id":"<expected_current_version_uuid>"}'
```

## Versions

Inspect skill version history and publish versioned SKILL.md content.

List published versions for a skill.

### GET `/skills/{slug}/versions`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/versions"
```

Publish a new version, or materialize a conflict draft when the expected base is stale.

### POST `/skills/{slug}/versions`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/versions" \
  -H "Content-Type: application/json" \
  -d '{"version":""}'
```

Fetch the manifest JSON for a specific version.

### GET `/skills/{slug}/versions/{version}/manifest`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/versions/$VERSION/manifest"
```

## Collaboration

Manage collaborators and draft conflict-resolution workflows.

List collaborators for a skill.

### GET `/skills/{slug}/collaborators`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/collaborators"
```

Add or update a collaborator for a skill.

### PUT `/skills/{slug}/collaborators/{user_id}`

```bash
curl -sS -X PUT "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/collaborators/$USER_ID" \
  -H "Content-Type: application/json" \
  -d '{"role":"","user_id":"<user_uuid>"}'
```

Remove a collaborator from a skill.

### DELETE `/skills/{slug}/collaborators/{user_id}`

```bash
curl -sS -X DELETE "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/collaborators/$USER_ID"
```

Fetch a chat draft created during conflict handling.

### GET `/skills/{slug}/drafts/{draft_id}`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/drafts/$DRAFT_ID"
```

Fetch merge-state metadata for a conflicted draft.

### GET `/skills/{slug}/drafts/{draft_id}/merge-state`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/drafts/$DRAFT_ID/merge-state"
```

Resolve a conflicted draft and publish the selected result.

### POST `/skills/{slug}/drafts/{draft_id}/resolve-conflict`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/drafts/$DRAFT_ID/resolve-conflict" \
  -H "Content-Type: application/json" \
  -d '{"resolution_strategy":""}'
```

## Update Requests

Submit, review, discuss, accept, and reject proposed changes to public skills.

List update requests for a skill.

### GET `/skills/{slug}/update-requests`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/update-requests"
```

Create an update request proposing a change to a skill.

### POST `/skills/{slug}/update-requests`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/update-requests" \
  -H "Content-Type: application/json" \
  -d '{"body":"","title":""}'
```

Fetch update-request details.

### GET `/update-requests/{request_id}`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/update-requests/$REQUEST_ID"
```

Fetch the rendered diff for an update request.

### GET `/update-requests/{request_id}/diff`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/update-requests/$REQUEST_ID/diff"
```

List comments on an update request.

### GET `/update-requests/{request_id}/comments`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/update-requests/$REQUEST_ID/comments"
```

Add a comment to an update request.

### POST `/update-requests/{request_id}/comments`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/update-requests/$REQUEST_ID/comments" \
  -H "Content-Type: application/json" \
  -d '{"body":""}'
```

Accept an update request and publish its content as a new skill version.

### POST `/update-requests/{request_id}/accept`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/update-requests/$REQUEST_ID/accept" \
  -H "Content-Type: application/json" \
  -d '{"allow_outdated_base":true,"changelog":"","expected_current_version_id":"<expected_current_version_uuid>"}'
```

Reject an update request with a terminal status.

### POST `/update-requests/{request_id}/reject`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/update-requests/$REQUEST_ID/reject"
```

## Marketplace

Purchase paid skills and configure sponsor metadata used in published SKILL.md files.

Purchase access to a paid skill through Seren Core billing.

### POST `/skills/{slug}/purchase`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/purchase" \
  -H "Authorization: Bearer $SEREN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Update sponsor settings that are rendered into the published SKILL.md.

### PUT `/skills/{slug}/sponsor`

```bash
curl -sS -X PUT "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/sponsor" \
  -H "Content-Type: application/json" \
  -d '{"sponsor_mode":""}'
```

## GitHub

Inspect and retry forward publishing to the canonical GitHub skill repository.

Inspect forward-publish status for a skill's current GitHub bundle.

### GET `/skills/{slug}/github`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/github"
```

Retry a failed or skipped GitHub forward-publish job.

### POST `/skills/{slug}/github/retry`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/github/retry"
```

Re-fetch the canonical GitHub bundle at HEAD and reconcile it as a new gateway version (no-op when content_hash_bundle matches).

### POST `/skills/{slug}/github/sync-from-main`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/github/sync-from-main"
```

Stage one signed commit on the canonical branch deleting orphan paths (legacy `org-<uuid>` placeholders left behind by a folder rename). Owner-only; requires `confirm: true` and a matching `expected_orphan_paths`.

### POST `/skills/{slug}/github/reconcile-orphans`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/skills/$SKILL_SLUG/github/reconcile-orphans" \
  -H "Content-Type: application/json" \
  -d '{"confirm":true,"dry_run":true,"expected_orphan_paths":[""]}'
```

## Admin

Operator-only inventory of canonical-repo paths the gateway has no row for. Read-only; pair with the per-skill `POST /skills/{slug}/github/reconcile-orphans` to delete.

Operator-only inventory of canonical-repo paths the gateway has no row for. Read-only; pair with `POST /skills/{slug}/github/reconcile-orphans` to delete.

### GET `/admin/skills/orphan-folders`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/admin/skills/orphan-folders"
```

## Identity

Manage Git author identity and organization folder mappings.

Fetch the authenticated caller's Git author identity.

### GET `/git-identity`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/git-identity"
```

Create or update the authenticated caller's Git author identity.

### PUT `/git-identity`

```bash
curl -sS -X PUT "https://api.serendb.com/publishers/seren-skills/git-identity" \
  -H "Content-Type: application/json" \
  -d '{"display_name":"my-agent","git_email":""}'
```

Fetch an organization's canonical skill folder mapping.

### GET `/organizations/{org_id}/folder`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/organizations/$ORGANIZATION_ID/folder"
```

Create an organization's canonical skill folder mapping.

### POST `/organizations/{org_id}/folder`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/organizations/$ORGANIZATION_ID/folder" \
  -H "Content-Type: application/json" \
  -d '{"folder_slug":"my-publisher"}'
```

Update an organization's canonical skill folder mapping.

### PUT `/organizations/{org_id}/folder`

```bash
curl -sS -X PUT "https://api.serendb.com/publishers/seren-skills/organizations/$ORGANIZATION_ID/folder" \
  -H "Content-Type: application/json" \
  -d '{"folder_slug":"my-publisher"}'
```

Update an organization's canonical skill folder mapping.

### PATCH `/organizations/{org_id}/folder`

```bash
curl -sS -X PATCH "https://api.serendb.com/publishers/seren-skills/organizations/$ORGANIZATION_ID/folder" \
  -H "Content-Type: application/json" \
  -d '{"folder_slug":"my-publisher"}'
```

Transfer ownership of a placeholder folder slug to the caller's organization.

### POST `/organizations/{org_id}/folder/transfer`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-skills/organizations/$ORGANIZATION_ID/folder/transfer" \
  -H "Content-Type: application/json" \
  -d '{"folder_slug":"my-publisher"}'
```

## Usage

Inspect usage events and billing summaries for the authenticated caller.

List usage events for the authenticated caller.

### GET `/usage`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/usage"
```

Summarize usage events and billing amounts for the authenticated caller.

### GET `/usage/summary`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-skills/usage/summary"
```
