API Reference
REST API for the SkillX marketplace. Base URL: https://skillx.sh
Authentication
Session Cookie
Browser-based auth via Better Auth + GitHub OAuth. Session set automatically after login. Expires after 7 days, refreshes after 1 day of activity.
API Key (Bearer Token)
For CLI and external integrations. Format: sx_ prefix + 64 hex characters. Keys stored as SHA-256 hashes.
Error Format
All errors return { "error": "message" }. 500 errors include an additional "details" field.
Search
/api/search?q=<query>Auth: OptionalSearch skills via hybrid keyword + semantic engine. Authenticated users get personalized favorite boost.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| q | string | Yes | Search query |
| category | string | No | Filter by category |
| is_paid | string | No | "true" or "false" |
| limit | number | No (20) | Max results (max 100) |
Response
{
"results": [
{
"id": "uuid",
"name": "Skill Name",
"slug": "skill-name",
"description": "...",
"category": "development",
"avg_rating": 8.5,
"install_count": 1200,
"github_stars": 450,
"final_score": 0.82,
"rrf_score": 0.031,
"semantic_rank": 2,
"keyword_rank": 5
}
],
"count": 1
}- Returns empty results if no "q" param provided.
Errors
/api/searchAuth: OptionalSame search via JSON body. Preferred for API integrations.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| query | string | Yes | Search query |
| category | string | No | Filter by category |
| is_paid | boolean | No | Filter free/paid |
| limit | number | No (20) | Max results (max 100) |
Request Body
{
"query": "kubernetes deploy",
"category": "devops",
"is_paid": false,
"limit": 20
}Response
Same as GET /api/search
Errors
Skills
/api/skills/:slugAuth: OptionalFetch full skill details with reviews and rating summary. Authenticated users see isFavorited status.
Response
{
"skill": { "id": "uuid", "name": "...", "slug": "...", "content": "...", ... },
"reviews": [{ "id": "...", "content": "...", "created_at": 1707955200000 }],
"isFavorited": false,
"ratingSummary": { "avgRating": 8.5, "ratingCount": 42 }
}Errors
/api/skills/:slug/rateAuth: Session requiredRate a skill (0-10 scale). Upserts — re-rating updates existing score.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| score | number | Yes | Rating 0-10 inclusive |
Request Body
{ "score": 8.5 }Response
{ "success": true, "avg_rating": 8.2, "rating_count": 43 }Errors
/api/skills/:slug/reviewAuth: NoneList reviews for a skill, newest first (max 100).
Response
{
"reviews": [
{
"id": "review-...",
"content": "Excellent skill for Kubernetes deployment",
"is_agent": false,
"created_at": 1707955200000
}
]
}Errors
/api/skills/:slug/reviewAuth: Session requiredSubmit a text review for a skill.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | 1-2000 characters |
Request Body
{ "content": "This skill saved me hours of work!" }Response
{ "success": true, "review": { "id": "review-...", "content": "...", ... } }Errors
/api/skills/:slug/favoriteAuth: Session requiredToggle favorite status. Adds if not favorited, removes if already favorited.
Response
{ "favorited": true }- favorited: true = added, false = removed. No request body needed.
Errors
User & API Keys
/api/reportAuth: API Key requiredReport skill execution outcome. Used by CLI to track success rates.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| skill_slug | string | Yes | Must match existing skill |
| outcome | string | Yes | "success", "failure", or "partial" |
| model | string | No | AI model used |
| duration_ms | number | No | Execution time in ms |
Request Body
{
"skill_slug": "kubernetes-deploy",
"outcome": "success",
"model": "claude-sonnet-4-5-20250929",
"duration_ms": 12500
}Response
{ "success": true }Errors
/api/user/api-keysAuth: Session requiredList current user's active (non-revoked) API keys with masked values.
Response
{
"keys": [
{
"id": "key-...",
"name": "My CLI Key",
"key_masked": "sx_a1b2c...",
"last_used_at": 1707955200000,
"created_at": 1707868800000
}
]
}Errors
/api/user/api-keysAuth: Session requiredGenerate a new API key. Plaintext returned once — not stored.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | No ("Default") | Key label (max 100 chars) |
Request Body
{ "name": "My CLI Key" }Response
{
"success": true,
"key": "sx_a1b2c3d4e5f6...",
"message": "Save this key securely. It will not be shown again."
}- The plaintext key is only returned in this response. Store it securely.
Errors
/api/user/api-keysAuth: Session requiredRevoke an API key (soft delete).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Key ID to revoke |
Request Body
{ "id": "key-..." }Response
{ "success": true }Errors
Leaderboard & Admin
/api/leaderboardAuth: NonePaginated skill leaderboard with composite scoring and signal badges. Cached in KV (5min TTL).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| sort | string | No ("best") | "best", "rating", "installs", "trending", or "newest" |
| offset | number | No (0) | Pagination offset |
| limit | number | No (20) | Results per page (max 50) |
Response
{
"entries": [
{
"rank": 1,
"slug": "skill-name",
"name": "Skill Name",
"author": "author",
"installs": 1200,
"rating": 8.5,
"badges": ["top-rated", "popular"]
}
],
"hasMore": true
}- hasMore: true indicates more pages at offset + limit.
- Badges: "top-rated", "popular", "trending", "well-maintained", "community-pick" (based on p90 thresholds).
/api/admin/seedAuth: Admin (X-Admin-Secret header)Bulk upsert skills and index into Vectorize. For seeding data.
Request Body
[
{
"name": "Kubernetes Deploy",
"slug": "kubernetes-deploy",
"description": "Deploy to K8s clusters",
"content": "Full skill content...",
"author": "skillx",
"category": "devops"
}
]Response
{ "skills": 30, "vectors": 120, "scoresRecomputed": 30 }- Request body must be an array of skill objects.
- Required fields: name, slug, description, content, author, category.