SkillHub
Sign in

Developers

SkillHub ships a public REST API, an OpenAPI 3.0 specification, and official SDKs for TypeScript and Python. This page is the entry point for anyone integrating SkillHub into another tool, agent, or pipeline — whether you are calling 5 endpoints per day or 5,000 per second.

Overview

The SkillHub API is the same surface the web UI reads from: every list page, every detail page, every version diff, and every full-text search hits a versioned REST endpoint under /api/v1. The endpoint set, request shape, and response envelope are all auto-published to OpenAPI 3.0 so SDKs can be generated without hand-writing types.

Base URL

All API calls target the API origin directly (the same host the SDK examples use). For local dev the default is http://localhost:3001; production points to https://api.skillhub.dev. The published OpenAPI spec lists both under its `servers` block.

# API direct (default — matches Swagger servers + SDK README)
SKILLHUB_BASE_URL=http://localhost:3001

# Sandbox proxy (dev env — the SDK examples default to this)
# SKILLHUB_BASE_URL=http://localhost:3099

Authentication

Cookie-authenticated endpoints accept the session cookie set by GitHub OAuth or email sign-in (`skillhub_session`, HTTP-only, SameSite=Lax, Secure on prod). Public endpoints (skill catalog, search, skill detail, version diff, categories, sources) require no auth. The OpenAPI spec marks each endpoint with a lock icon when cookieAuth is required.

Quickstart

Five steps to your first successful API call. Each step links to a runnable example in the SDK package.

1. Get an API key

Self-serve API keys ship as of M5.4. Sign in, go to [API keys](/me/settings/api-keys), click **Create key**. The plaintext `shkm_<35 chars>` is shown EXACTLY ONCE — copy it into your CI secret store immediately. The key prefix (`shkm_<10 hex>`) is the human-readable identifier in the dashboard.

2. Install the SDK

TypeScript and Python SDKs are auto-generated from /openapi.json. They export typed operation helpers (listSkills, getSkillDetail, …) plus the full response schema for every endpoint.

pnpm add @skillhub/sdk-typescript
pip install skillhub-sdk

3. First call — list skills

The cheapest public call. Lists the first page of the skill catalog with optional q/tag/category/source/sort filters.

import { createSkillHubClient, listSkills } from '@skillhub/sdk-typescript';

const client = createSkillHubClient({
  baseUrl: process.env.SKILLHUB_BASE_URL ?? 'http://localhost:3001',
});

// (1a) plain list, first page, default sort = stars
const r = await listSkills(client, { page: 1, page_size: 3 });
console.log('total:', r.data?.total, '· pages:', r.data?.total_pages);
for (const item of r.data?.items ?? []) {
  console.log(`  - ${item.name} (source=${item.source_name}, stars=${item.source_stars})`);
}

4. Try a skill online

POST /api/v1/skills/:source/:slug/try runs the skill body against your input inside an isolated Docker sandbox. CookieAuth required; rate limit 3/day free, 100/day Pro.

import { createSkillHubClient, trySkill } from '@skillhub/sdk-typescript';

const client = createSkillHubClient({
  baseUrl: process.env.SKILLHUB_BASE_URL ?? 'http://localhost:3001',
  // trySkill requires the skillhub_session cookie (cookieAuth).
  cookie: `skillhub_session=${process.env.SKILLHUB_SESSION ?? ''}`,
});

const r = await trySkill(client, {
  source: 'clawhub',
  slug: 'ai-ppt-generator',
  input: 'Make a slide deck about cats.',
});

if (r.response.status === 200) {
  console.log('output:', r.data?.output);
} else {
  console.error(r.response.status, r.data);
}
from skillhub_sdk import Client

client = Client(base_url="http://localhost:3001")

# (Python SDK exposes the full schema; helpers are auto-generated
# from /openapi.json. See packages/sdk-python for the surface.)
r = client.sync_detailed(
    "api_v1_skills_source_slug_try",
    path_params={"source": "clawhub", "slug": "ai-ppt-generator"},
    body={"input": "Make a slide deck about cats."},
)
print(r.status_code, r.content)

5. Convert between 5 skill formats

The transcoder (M4.3) converts between cursor / claude / mcp / prompt / workflow formats with fidelity tracking. It runs inside the sync-worker package, not over HTTP — invoke via the script wrapper.

# The transcoder is NOT exposed over HTTP — it runs inside the
# sync-worker package. Invoke via the script wrapper:
bash scripts/transcode-demo.sh clawhub <skill-slug>

# That runs the 5-format matrix (cursor ↔ claude ↔ mcp ↔
# prompt ↔ workflow) against the skill's current_version body and
# prints the per-format fidelity level + lostFields set.

API reference

Two views over the same published spec — the raw JSON for tooling and codegen, and the Swagger UI for human browsing.

OpenAPI 3.0 spec (JSON)

Raw /openapi.json — feed this into openapi-generator-cli, openapi-typescript, openapi-python-client, or your contract-test harness. 76 paths / 90 operations, cookieAuth security scheme included. /openapi.json ↗

Swagger UI

Interactive /docs explorer — browse by tag, expand request/response shapes, copy curl examples. Lock icons mark cookie-authenticated endpoints. /docs ↗

Rate limits

Two layers. The outer layer protects every endpoint from per-IP abuse; the inner layer caps specific actions per user so a single misbehaving caller can't burn down a shared budget.

Global — per-IP, Redis-backed

All endpoints share a 60 requests / minute / IP sliding window, enforced by @fastify/rate-limit with a Redis store. Returns 429 with the unified ErrorEnvelope when exceeded. skipOnError is true: if Redis is down, the limiter fails open and never 503s the API.

Per-user, per-action — bumpRateLimit (M3.6 #4)

Auth and mutation endpoints cap by user (or email or IP, depending on the action). The bumpRateLimit helper applies a sliding-window count via INSERT … ON CONFLICT DO UPDATE on auth_attempts and returns a 429 envelope when any dim exceeds its budget.

ActionLimit
POST /try (free tier)3 / day / user
POST /try (Pro tier)100 / day / user
POST /fork1 / hour / user
POST /votes5 / hour / user
POST /comments10 / hour / user
POST /auth/email/login5 / min / email + 20 / hour / IP

Errors

Every error response uses the unified envelope shaped by the global setErrorHandler / toApiErrorBody funnel. The HTTP status code carries the broad category; the body's `error.code` field is the machine-readable identifier; `error.message` is the localized human-readable message (locale follows the `Accept-Language` header).

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests, please slow down."
  }
}

400 — Bad request

Validation failure (Ajv schema reject on body / querystring / params). error.code is one of FST_ERR_VALIDATION, INVALID_QUERY, INVALID_PARAMS, INVALID_BODY.

401 — Unauthenticated

CookieAuth required but no valid skillhub_session cookie was sent (or the session has expired). error.code is UNAUTHENTICATED.

404 — Not found

Resource does not exist (skill slug, version id, user id, …). error.code is NOT_FOUND.

429 — Rate limited

Either the global per-IP limiter or the per-action bumpRateLimit dim exceeded. error.code is RATE_LIMITED; the Retry-After header carries the remaining window.

500 — Internal error

Unexpected server-side failure. Captured to Sentry (or console-fallback in dev). error.code is INTERNAL; the message is the same on every locale.

SDK downloads

Both SDKs are auto-generated from /openapi.json on every API change. Pin to the SkillHub API version they were generated against (currently 0.18.0).

TypeScript — @skillhub/sdk-typescript

openapi-fetch under the hood, with typed operation helpers for every endpoint. Tree-shakeable; ships the full response schema as types.

# Install
pnpm add @skillhub/sdk-typescript

Python — skillhub-sdk

openapi-python-client output, httpx transport, attrs models. Requires Python ≥ 3.10.

# Install
pip install skillhub-sdk

Changelog

v0.18.0 (M5.1 + M5.2) shipped the public OpenAPI spec and the auto-generated TypeScript + Python SDKs. v0.19.0 (this page) is the developer-facing entry point. Self-serve API keys land in M5.4; the SDK adds 1-2 partner integrations in M5.5.

Browse skills