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.

Authorization: Bearer sx_<64-hex-chars>

Error Format

All errors return { "error": "message" }. 500 errors include an additional "details" field.

Skills

GET/api/skills/:slugAuth: Optional

Fetch 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

400Missing slug param
404Invalid slug
POST/api/skills/:slug/rateAuth: Session required

Rate a skill (0-10 scale). Upserts — re-rating updates existing score.

Parameters

NameTypeRequiredDescription
scorenumberYesRating 0-10 inclusive

Request Body

{ "score": 8.5 }

Response

{ "success": true, "avg_rating": 8.2, "rating_count": 43 }

Errors

400Invalid score value
401Not logged in
404Invalid slug
GET/api/skills/:slug/reviewAuth: None

List 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

404Invalid slug
POST/api/skills/:slug/reviewAuth: Session required

Submit a text review for a skill.

Parameters

NameTypeRequiredDescription
contentstringYes1-2000 characters

Request Body

{ "content": "This skill saved me hours of work!" }

Response

{ "success": true, "review": { "id": "review-...", "content": "...", ... } }

Errors

400Empty content
400Too long
401Not logged in
404Invalid slug
POST/api/skills/:slug/favoriteAuth: Session required

Toggle favorite status. Adds if not favorited, removes if already favorited.

Response

{ "favorited": true }
  • favorited: true = added, false = removed. No request body needed.

Errors

401Not logged in
404Invalid slug

User & API Keys

POST/api/reportAuth: API Key required

Report skill execution outcome. Used by CLI to track success rates.

Parameters

NameTypeRequiredDescription
skill_slugstringYesMust match existing skill
outcomestringYes"success", "failure", or "partial"
modelstringNoAI model used
duration_msnumberNoExecution time in ms

Request Body

{
  "skill_slug": "kubernetes-deploy",
  "outcome": "success",
  "model": "claude-sonnet-4-5-20250929",
  "duration_ms": 12500
}

Response

{ "success": true }

Errors

400Missing slug
400Invalid outcome
401Missing/invalid API key
404Invalid slug
GET/api/user/api-keysAuth: Session required

List 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

401Not logged in
POST/api/user/api-keysAuth: Session required

Generate a new API key. Plaintext returned once — not stored.

Parameters

NameTypeRequiredDescription
namestringNo ("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

401Not logged in
DELETE/api/user/api-keysAuth: Session required

Revoke an API key (soft delete).

Parameters

NameTypeRequiredDescription
idstringYesKey ID to revoke

Request Body

{ "id": "key-..." }

Response

{ "success": true }

Errors

400Missing ID
401Not logged in
404Invalid/revoked key

Leaderboard & Admin

GET/api/leaderboardAuth: None

Paginated skill leaderboard with composite scoring and signal badges. Cached in KV (5min TTL).

Parameters

NameTypeRequiredDescription
sortstringNo ("best")"best", "rating", "installs", "trending", or "newest"
offsetnumberNo (0)Pagination offset
limitnumberNo (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).
POST/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.

Errors

400Non-array body
401Missing/wrong admin secret