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

ParameterTypeDefaultDescription
limitnumber-Max results
offsetnumber0Pagination offset
categorystring-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

ParameterTypeDefaultDescription
limitnumberPage size. Omit it and the response is a bare array; pass it and the response is an envelope.
offsetnumber0Pagination 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.

FieldTypeRequiredDescription
artifactIdstringNoArtifact ID when installing from an artifact
namestringNoSkill name (used for artifact install)
descriptionstringNoSkill description
categorystringNoSkill category
registrystringNoAlternate 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

Statuserror.codeDescription
404NOT_FOUNDSkill doesn’t exist in the marketplace
429EXECUTION_RUNNINGAn execution is running in this workspace
500INTERNAL_ERRORInstall 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

Statuserror.codeDescription
404NOT_FOUNDSkill not in the workspace’s library
429EXECUTION_RUNNINGCannot 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…"
  }
}
Statuserror.codeDescription
400INVALID_INPUT:versionNumber is not a positive integer
404NOT_FOUNDThe 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

FieldTypeRequiredDescription
inputstringYesInput prompt for the skill
attachmentsarrayNoFile attachments
connectorobjectNoSource 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

StatusCodeDescription
400INVALID_INPUTMissing or unusable input
402INSUFFICIENT_CREDITSNot enough Dollarinos
404NOT_FOUNDSkill not installed
409/429EXECUTION_RUNNINGAnother execution is already active
429RATE_LIMITEDPer-user execution rate limit exceeded
500EXECUTION_FAILEDThe run could not be started

Shape note: this one route still answers service-level failures in the pre-envelope shape — { "error": "<CODE>", "message": "…" }, where error is 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
}