Skills API Endpoints
REST API endpoints for managing skills.
List Marketplace Skills
Get all available skills from the marketplace. This is a public endpoint.
GET /api/v1/marketplace/skills
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | - | Max results |
offset | number | 0 | Pagination offset |
category | string | - | Filter by category |
Example
curl "https://clanker.net/api/v1/marketplace/skills?category=development&limit=10"
Response
[
{
"slug": "readme-generator",
"name": "README Generator",
"description": "Generate comprehensive README files",
"category": "productivity",
"repository": "clanker-skills/readme-generator"
}
]
List Categories
Get all skill categories. This is a public endpoint.
GET /api/v1/marketplace/skills/categories
Example
curl https://clanker.net/api/v1/marketplace/skills/categories
Response
[
{ "id": "productivity", "name": "Productivity", "count": 45 },
{ "id": "development", "name": "Development", "count": 120 },
{ "id": "creative", "name": "Creative", "count": 30 }
]
Get Skill Details
Get detailed information about a specific skill from the marketplace. This is a public endpoint.
GET /api/v1/marketplace/skills/:slug
Example
curl https://clanker.net/api/v1/marketplace/skills/readme-generator
Response
{
"slug": "readme-generator",
"name": "README Generator",
"description": "Generate comprehensive README files for your projects",
"category": "productivity",
"repository": "clanker-skills/readme-generator",
"prompt": "# README Generator\n\n...",
"author": "clanker-skills",
"version": "1.0.0"
}
List User Skills
Get the skills installed in the caller’s active workspace.
GET /api/v1/skills
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | — | Page size. Omit it and the response is a bare array; pass it and the response is an envelope. |
offset | number | 0 | Pagination offset (only meaningful with limit) |
Example
curl https://clanker.net/api/v1/skills \
-H "x-auth-token: YOUR_AUTH_TOKEN"
Response
[
{
"name": "README Generator",
"slug": "readme-generator",
"description": "Generate comprehensive README files",
"category": "productivity",
"prompt": "# README Generator\n\n...",
"repository": "clanker-skills/readme-generator",
"commitHash": "a1b2c3d"
}
]
repository and commitHash are filled in from the marketplace catalog and are
absent for a skill you authored yourself. With ?limit=10:
{
"items": [ ... ],
"total": 42,
"limit": 10,
"offset": 0,
"hasMore": true
}
Install Skill
Add a marketplace skill to user’s library, or install a user-created skill from an artifact.
POST /api/v1/skills/:slug/install
Request Body
Every field is optional — the slug in the path carries the essential information, and sending no body at all is a legitimate call.
| Field | Type | Required | Description |
|---|---|---|---|
artifactId | string | No | Artifact ID when installing from an artifact |
name | string | No | Skill name (used for artifact install) |
description | string | No | Skill description |
category | string | No | Skill category |
registry | string | No | Alternate registry base URL to install from |
Example (Marketplace)
curl -X POST https://clanker.net/api/v1/skills/readme-generator/install \
-H "x-auth-token: YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
Example (From Artifact)
curl -X POST https://clanker.net/api/v1/skills/my-custom-skill/install \
-H "x-auth-token: YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"artifactId": "a1b2c3d4-5678-90ab-cdef-1234567890ab", "name": "My Custom Skill", "description": "A custom skill", "category": "general"}'
Response
The installed skill record, returned flat — there is no success wrapper:
{
"name": "README Generator",
"slug": "readme-generator",
"description": "Generate comprehensive README files",
"category": "productivity",
"prompt": "# README Generator\n\n...",
"bundleType": "text",
"storagePath": "workspaces/7c2e…/skills/readme-generator",
"repository": "clanker-skills/readme-generator",
"commitHash": "a1b2c3d",
"filesCount": 3
}
Errors
| Status | error.code | Description |
|---|---|---|
| 404 | NOT_FOUND | Skill doesn’t exist in the marketplace |
| 429 | EXECUTION_RUNNING | An execution is running in this workspace |
| 500 | INTERNAL_ERROR | Install failed |
An EXECUTION_RUNNING response carries isRunning: true as a top-level
sibling of error, not inside details — clients branch on it to offer “view
the running execution” instead of surfacing a failure:
{
"error": {
"code": "EXECUTION_RUNNING",
"message": "Cannot install skill while an execution is running"
},
"isRunning": true
}
Uninstall Skill
Remove a skill from user’s library.
POST /api/v1/skills/:slug/uninstall
Example
curl -X POST https://clanker.net/api/v1/skills/readme-generator/uninstall \
-H "x-auth-token: YOUR_AUTH_TOKEN"
Response
{
"success": true
}
Errors
| Status | error.code | Description |
|---|---|---|
| 404 | NOT_FOUND | Skill not in the workspace’s library |
| 429 | EXECUTION_RUNNING | Cannot uninstall during an execution (carries isRunning: true) |
Version History
Skills are editable — by you and by agents — so every write records a version.
GET /api/v1/skills/:slug/versions
Returns a bare array, newest first, with active marking the version the
live bundle currently serves.
curl https://clanker.net/api/v1/skills/readme-generator/versions \
-H "x-auth-token: YOUR_AUTH_TOKEN"
[
{
"id": 8,
"workspaceId": "7c2e…",
"skillId": 42,
"versionNumber": 3,
"contentChecksum": "9f1c2a80…",
"storagePath": "workspaces/7c2e…/skill-versions/readme-generator/3",
"bundleType": "text",
"prompt": "# README Generator\n\n...",
"name": "README Generator",
"description": "Generate comprehensive README files",
"createdBy": "3ab91c22-…",
"note": null,
"createdAt": "2026-08-01T10:12:03.441Z",
"active": true
}
]
404 NOT_FOUND when the slug is not installed in this workspace.
Restore a version
POST /api/v1/skills/:slug/versions/:versionNumber/restore
Non-destructive. Restoring v2 while v3 exists leaves v3 in the history and creates a new version carrying v2’s content — so an accidental restore is itself undoable.
curl -X POST https://clanker.net/api/v1/skills/readme-generator/versions/2/restore \
-H "x-auth-token: YOUR_AUTH_TOKEN"
{
"success": true,
"restoredFrom": 2,
"skill": {
"slug": "readme-generator",
"contentChecksum": "4d5e6f70…"
}
}
| Status | error.code | Description |
|---|---|---|
| 400 | INVALID_INPUT | :versionNumber is not a positive integer |
| 404 | NOT_FOUND | The skill, or that version of it, does not exist |
Execute Skill
Start a skill execution with input.
POST /api/v1/skills/:slug/run
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
input | string | Yes | Input prompt for the skill |
attachments | array | No | File attachments |
connector | object | No | Source connector config (e.g., GitHub repo/branch) |
Example
curl -X POST https://clanker.net/api/v1/skills/readme-generator/run \
-H "x-auth-token: YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"input": "Create a README for my TypeScript CLI tool"
}'
Response
{
"executionId": "exec_abc123def456",
"skillName": "README Generator",
"status": "started",
"message": "Execution started. Connect to SSE stream for real-time updates.",
"sseUrl": "/api/v1/executions/exec_abc123def456/events"
}
The run has already started by the time you get this, so open the stream
immediately: mint a signed SSE URL with
GET /api/v1/executions/:id/stream-token and connect to it. That stream
replays from the first event, so nothing emitted before you connected is lost.
See Executions.
This endpoint is for interactive use. For bots, CI and anything that must survive a restart, use Workflows — they queue and resume; this does neither.
Errors
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_INPUT | Missing or unusable input |
| 402 | INSUFFICIENT_CREDITS | Not enough Dollarinos |
| 404 | NOT_FOUND | Skill not installed |
| 409/429 | EXECUTION_RUNNING | Another execution is already active |
| 429 | RATE_LIMITED | Per-user execution rate limit exceeded |
| 500 | EXECUTION_FAILED | The run could not be started |
Shape note: this one route still answers service-level failures in the pre-envelope shape —
{ "error": "<CODE>", "message": "…" }, whereerroris the code string, not an object, and any structured detail is spread flat alongside it. Auth and rate-limit rejections from the same route use the standard{ "error": { "code", "message" } }envelope. Read the code defensively:typeof body.error === "string" ? body.error : body.error.code.
{
"error": "INSUFFICIENT_CREDITS",
"message": "Minimum 50 Ds required. You have 12 available.",
"balance": 12,
"availableBalance": 12,
"minimumRequired": 50
}