{"openapi":"3.1.0","info":{"title":"skills-hub.ai API","description":"> **Signed in reference.** To see the endpoints available to your account or organization and run authenticated requests with one click, open the [interactive reference on skills-hub.ai](https://skills-hub.ai/docs/api-reference).\n\n<!--/signin-banner-->\n\nPublic REST API for discovering, publishing, and managing AI coding skills. All endpoints under /api/v1.","version":"1.0.0","contact":{"name":"skills-hub.ai","url":"https://skills-hub.ai","email":"support@skills-hub.ai"},"license":{"name":"MIT","url":"https://opensource.org/licenses/MIT"}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token from POST /api/v1/auth/login"},"ApiKeyAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"API key in format: ApiKey <key>"}},"schemas":{}},"paths":{"/api/v1/auth/github":{"get":{"summary":"Start GitHub OAuth login","tags":["Authentication"],"description":"Public. Redirects the browser to GitHub's `authorize` endpoint with an HMAC-signed `state` parameter for CSRF protection. The client should follow the redirect to begin GitHub sign-in.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}},"/api/v1/auth/github/callback":{"post":{"summary":"Complete GitHub OAuth login","tags":["Authentication"],"description":"Public. Exchanges the GitHub `code` for account tokens after verifying the signed `state`. Sets an httpOnly `refreshToken` cookie and returns a short-lived `accessToken` plus the public user profile.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["accessToken","expiresIn","user"],"properties":{"accessToken":{"type":"string","description":"Short-lived JWT access token."},"expiresIn":{"type":"integer","description":"Access token lifetime in seconds.","example":900},"user":{"type":"object","required":["id","username","displayName","avatarUrl","bio","githubUrl","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}}}}},"/api/v1/auth/google":{"get":{"summary":"Start Google OAuth login","tags":["Authentication"],"description":"Public. Redirects the browser to Google's OAuth consent screen with an HMAC-signed `state` parameter. Returns `500 GOOGLE_NOT_CONFIGURED` if Google OAuth credentials are not set on the server.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}},"/api/v1/auth/google/callback":{"post":{"summary":"Complete Google OAuth login","tags":["Authentication"],"description":"Public. Exchanges the Google `code` for account tokens after verifying the signed `state`. Sets an httpOnly `refreshToken` cookie and returns a short-lived `accessToken` plus the public user profile.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["accessToken","expiresIn","user"],"properties":{"accessToken":{"type":"string"},"expiresIn":{"type":"integer","example":900},"user":{"type":"object","required":["id","username","displayName","avatarUrl","bio","githubUrl","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}}}}},"/api/v1/auth/register":{"post":{"summary":"Register with email and password","tags":["Authentication"],"description":"Public. Creates a new account from `email`, `password`, and `username`. Sets an httpOnly `refreshToken` cookie and returns a short-lived `accessToken` plus the public user profile.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["accessToken","expiresIn","user"],"properties":{"accessToken":{"type":"string"},"expiresIn":{"type":"integer","example":900},"user":{"type":"object","required":["id","username","displayName","avatarUrl","bio","githubUrl","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}}}}},"/api/v1/auth/login":{"post":{"summary":"Log in with email and password","tags":["Authentication"],"description":"Public. Authenticates `email`/`password`, sets an httpOnly `refreshToken` cookie, and returns a short-lived `accessToken` plus the public profile. Brute-force protected: repeated failures lock the account (keyed on email + IP) and return `429 TOO_MANY_ATTEMPTS` with a `Retry-After` header.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["accessToken","expiresIn","user"],"properties":{"accessToken":{"type":"string"},"expiresIn":{"type":"integer","example":900},"user":{"type":"object","required":["id","username","displayName","avatarUrl","bio","githubUrl","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}}}}},"/api/v1/auth/refresh":{"post":{"summary":"Refresh the access token","tags":["Authentication"],"description":"Reads the httpOnly `refreshToken` cookie, rotates it, and returns a new short-lived `accessToken`. Requires a valid refresh cookie; responds `401` if none is present or it is invalid/revoked.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["accessToken","expiresIn"],"properties":{"accessToken":{"type":"string"},"expiresIn":{"type":"integer","example":900}}}}}}}}},"/api/v1/auth/session":{"delete":{"summary":"Log out and revoke the session","tags":["Authentication"],"description":"Revokes the refresh token from the httpOnly cookie (if present) and clears the cookie. Idempotent: always returns `{ success: true }` even when no session cookie is set.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/auth/verify-email":{"post":{"summary":"Verify email address with token","tags":["Authentication"],"description":"Public. Confirms an email address using the one-time `token` from the verification email and marks the account verified. Responds with an error if the token is invalid or expired.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/auth/send-verification":{"post":{"summary":"Resend the email verification link","tags":["Authentication"],"description":"Authenticated. Sends a fresh verification email to the signed-in user's address. Tightly rate-limited to one request per minute to prevent inbox flooding.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/auth/forgot-password":{"post":{"summary":"Request a password reset email","tags":["Authentication"],"description":"Public. Sends a password-reset link if an account exists for the given `email`. Always returns `{ success: true }` regardless of whether the address is registered, to prevent account enumeration.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/auth/reset-password":{"post":{"summary":"Reset password with a reset token","tags":["Authentication"],"description":"Public. Sets a new password using the one-time `token` from the reset email. Fails if the token is invalid or expired.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/users/me":{"get":{"summary":"Get my profile","tags":["Users & Profiles"],"description":"Authenticated. Returns the signed-in user's private profile, including PII such as `email` that is never exposed on the public profile endpoint.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Private profile of the signed-in user (includes email PII).","required":["id","username","displayName","avatarUrl","bio","githubUrl","email","emailVerified","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"email":{"type":["string","null"]},"emailVerified":{"type":"boolean"},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}},"patch":{"summary":"Update my profile","tags":["Users & Profiles"],"description":"Authenticated. Updates the signed-in user's editable profile fields (such as display name, bio, and links). `username` is immutable after first sign-in and cannot be changed here.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Updated private profile of the signed-in user.","required":["id","username","displayName","avatarUrl","bio","githubUrl","email","emailVerified","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"email":{"type":["string","null"]},"emailVerified":{"type":"boolean"},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}}},"/api/v1/users/me/analytics":{"get":{"summary":"Get my creator analytics","tags":["Users & Profiles"],"description":"Authenticated. Returns aggregate analytics for the signed-in user's published skills (such as views and installs). Sent with `Cache-Control: private, no-cache`.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["dailyInstalls","installsByPlatform","topSkills","likesOverTime","ratingDistribution","totals"],"properties":{"dailyInstalls":{"type":"array","items":{"type":"object","required":["date","count"],"properties":{"date":{"type":"string","description":"YYYY-MM-DD"},"count":{"type":"integer"}}}},"installsByPlatform":{"type":"array","items":{"type":"object","required":["platform","count"],"properties":{"platform":{"type":"string"},"count":{"type":"integer"}}}},"topSkills":{"type":"array","items":{"type":"object","required":["slug","name","installs","likes"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"installs":{"type":"integer"},"likes":{"type":"integer"}}}},"likesOverTime":{"type":"array","items":{"type":"object","required":["date","count"],"properties":{"date":{"type":"string","description":"YYYY-MM-DD"},"count":{"type":"integer"}}}},"ratingDistribution":{"type":"array","items":{"type":"object","required":["rating","count"],"properties":{"rating":{"type":"integer"},"count":{"type":"integer"}}}},"totals":{"type":"object","required":["skills","published","installs","likes","reviews","avgRating"],"properties":{"skills":{"type":"integer"},"published":{"type":"integer"},"installs":{"type":"integer"},"likes":{"type":"integer"},"reviews":{"type":"integer"},"avgRating":{"type":["number","null"]}}}}}}}}}}},"/api/v1/users/me/api-keys":{"post":{"summary":"Create an API key","tags":["Users & Profiles"],"description":"Authenticated. Issues a new personal API key for the signed-in user with an optional `expiresInDays`. The plaintext key is returned only once in this response and cannot be retrieved again.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Newly created API key. The plaintext `key` is returned only once and cannot be retrieved again.","required":["id","name","keyPrefix","key","lastUsedAt","expiresAt","createdAt","requestsLast30Days"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string","description":"Non-secret display prefix, e.g. 'sh_abc123...'"},"key":{"type":"string","description":"Full plaintext API key — shown only at creation."},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"requestsLast30Days":{"type":"integer","description":"Metered requests attributed to this key over the trailing 30 UTC days. Always 0 at creation."}}}}}}}},"get":{"summary":"List my API keys","tags":["Users & Profiles"],"description":"Authenticated. Returns metadata for the signed-in user's API keys (name, prefix, creation and expiry). Secret key material is never included.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","description":"API key metadata for the signed-in user. Secret key material is never included.","items":{"type":"object","required":["id","name","keyPrefix","lastUsedAt","expiresAt","createdAt","requestsLast30Days"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"requestsLast30Days":{"type":"integer","description":"Metered requests attributed to this key over the trailing 30 UTC days."}}}}}}}}}},"/api/v1/users/me/api-keys/{id}":{"delete":{"summary":"Revoke an API key","tags":["Users & Profiles"],"description":"Authenticated. Permanently revokes the signed-in user's API key identified by `:id`. Only the key's owner can revoke it; returns `{ success: true }` on completion.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/users/me/notification-prefs":{"get":{"summary":"Get my notification preferences","tags":["Users & Profiles"],"description":"Authenticated. Returns the signed-in user's notification preferences (such as which email notifications are enabled).","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Per-type notification opt-out preferences. Each key maps a notification type to a boolean; missing keys default to enabled.","additionalProperties":{"type":"boolean"},"propertyNames":{"enum":["NEW_FOLLOWER","NEW_SKILL_FROM_FOLLOWEE","SKILL_REVIEW","SKILL_FORKED","SKILL_UPDATED","SKILL_PUBLISHED","SKILL_REJECTED","AGENT_RUN_AWAITING_REVIEW","AGENT_RUN_DELIVERED","AGENT_RUN_FAILED","AGENT_RUN_REJECTED"]}}}}}}},"put":{"summary":"Update my notification preferences","tags":["Users & Profiles"],"description":"Authenticated. Replaces the signed-in user's notification preferences with the submitted settings and returns the updated preferences.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Updated per-type notification opt-out preferences.","additionalProperties":{"type":"boolean"},"propertyNames":{"enum":["NEW_FOLLOWER","NEW_SKILL_FROM_FOLLOWEE","SKILL_REVIEW","SKILL_FORKED","SKILL_UPDATED","SKILL_PUBLISHED","SKILL_REJECTED","AGENT_RUN_AWAITING_REVIEW","AGENT_RUN_DELIVERED","AGENT_RUN_FAILED","AGENT_RUN_REJECTED"]}}}}}}}},"/api/v1/users/{username}":{"get":{"summary":"Get a public user profile","tags":["Users & Profiles"],"description":"Public. Returns the public profile for `:username` (never exposes `email` or other PII). Optionally authenticated: when a valid token is supplied, the response reflects the viewer (for example, follow state).","parameters":[{"schema":{"type":"string"},"in":"path","name":"username","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Public profile — never exposes email or other PII. `userFollowing` reflects the authenticated viewer when a token is supplied.","required":["id","username","displayName","avatarUrl","bio","githubUrl","trustLevel","isAdmin","createdAt","skillCount","totalInstalls","followerCount","followingCount","userFollowing"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"bio":{"type":["string","null"]},"githubUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]},"isAdmin":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"followerCount":{"type":"integer"},"followingCount":{"type":"integer"},"userFollowing":{"type":"boolean"}}}}}}}}},"/api/v1/skills/":{"get":{"summary":"List and search skills","tags":["Skills"],"description":"Returns a cursor-paginated list of published, public skills. Public; an authenticated caller may scope to their own `DRAFT`/`PRIVATE`/`UNLISTED`/`ORG` skills. Supports `q`, `category`, `platform`, `minScore`, `author`, `source`, `official`, `visibility`, `sort` (e.g. `trending`, `most_installed`), and `searchMode=hybrid` for BM25 + vector fusion.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}},"post":{"summary":"Create a skill","tags":["Skills"],"description":"Creates a new `DRAFT` skill and its first version for the authenticated caller. Authenticated. Org-scoped skills (via `orgSlug`) require org membership and are limited to `ORG`/`DEPARTMENT`/`TEAM` visibility; orgs that gate new skills queue the draft for approval.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/skills/count":{"get":{"summary":"Count published skills","tags":["Skills"],"description":"Returns the total number of published, public skills as `{ count }`. Public; cached for one hour.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"}},"required":["count"]}}}}}}},"/api/v1/skills/{slug}":{"get":{"summary":"Get skill detail","tags":["Skills"],"description":"Returns full detail for one skill by `slug`: latest instructions, version history, composition, and media. Public for public skills; `PRIVATE`/`ORG`/`UNLISTED` skills require the author or an authorized member. Includes the caller's `userLiked`/`userBookmarked` flags when authenticated.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"SkillDetail — a SkillSummary plus latest instructions, version history, composition, media, and stateful-format siblings.","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"industry":{"type":"object","properties":{"value":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]}}},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string","enum":["PUBLIC","PRIVATE","UNLISTED","ORG","DEPARTMENT","TEAM"]},"platforms":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}},"qualityScore":{"type":["number","null"]},"aiQualityScore":{"type":["number","null"]},"qualityBreakdown":{"type":["object","null"],"properties":{"coherence":{"type":"integer"},"specificity":{"type":"integer"},"completeness":{"type":"integer"},"usefulness":{"type":"integer"}}},"aiSecurityVerdict":{"type":["string","null"]},"securityGrade":{"type":["string","null"]},"sourceRepoUrl":{"type":["string","null"]},"sourceVerified":{"type":"boolean"},"sdlcPhase":{"type":["string","null"]},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"userLiked":{"type":"boolean"},"userBookmarked":{"type":"boolean"},"avgRating":{"type":["number","null"]},"reviewCount":{"type":"integer"},"latestVersion":{"type":"string"},"isCertified":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"isComposition":{"type":"boolean"},"org":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"forkedFrom":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"author":{"type":"string"}}},"forkCount":{"type":"integer"},"isOfficial":{"type":"boolean"},"isSigned":{"type":"boolean"},"hasMemory":{"type":"boolean"},"isCurrent":{"type":"boolean"},"lastFreshnessCheckAt":{"type":["string","null"]},"freshnessReason":{"type":["string","null"]},"examples":{"type":["array","null"],"items":{"type":"object","properties":{"input":{"type":"string"},"output":{"type":"string"}}}},"externalSource":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"githubUrl":{"type":["string","null"]}}},"signing":{"type":["object","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"instructions":{"type":"string"},"githubRepoUrl":{"type":["string","null"]},"memory":{"type":["string","null"]},"examplesMd":{"type":["string","null"]},"calibration":{"type":["string","null"]},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"},"changelog":{"type":["string","null"]},"contentHash":{"type":["string","null"]},"qualityScore":{"type":["number","null"]},"createdAt":{"type":"string"}}}},"composition":{"type":["object","null"],"properties":{"description":{"type":["string","null"]},"children":{"type":"array","items":{"type":"object","properties":{"skill":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"qualityScore":{"type":["number","null"]}}},"sortOrder":{"type":"integer"},"isParallel":{"type":"boolean"}}}}}},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["SCREENSHOT","YOUTUBE"]},"url":{"type":"string"},"caption":{"type":["string","null"]},"sortOrder":{"type":"integer"}}}}},"required":["id","slug","name","description","instructions","versions","media"]}}}}}},"patch":{"summary":"Update skill metadata","tags":["Skills"],"description":"Updates a skill's metadata (name, description, category, platforms, visibility, tags, source URLs, etc.). Restricted to the skill author, an org `PUBLISHER`+ for org skills, or an admin. Changing the source URL resets source verification.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"The updated skill as a SkillSummary.","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string"}}},"platforms":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}},"qualityScore":{"type":["number","null"]},"sourceVerified":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"latestVersion":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","slug","name"]}}}}}},"delete":{"summary":"Delete a skill","tags":["Skills"],"description":"Permanently deletes a skill. Restricted to the author or an org `PUBLISHER`+ for org skills. Returns `{ success: true }`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/{slug}/related":{"get":{"summary":"Get related skills","tags":["Skills"],"description":"Returns detail-page discovery rails for a skill: `related` (shared tags), `sameSource` (same GitHub source repo), and `sameCategory`, de-duplicated across buckets. Public, published skills only; publicly cacheable. `limit` (1-12, default 6) caps each rail.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Detail-page discovery rails. Each bucket is an array of SkillSummary objects; buckets are de-duplicated across each other.","properties":{"related":{"type":"array","items":{"type":"object","description":"SkillSummary"}},"sameSource":{"type":"array","items":{"type":"object","description":"SkillSummary"}},"sameCategory":{"type":"array","items":{"type":"object","description":"SkillSummary"}}},"required":["related","sameSource","sameCategory"]}}}}}}},"/api/v1/skills/import-from-github":{"post":{"summary":"Import a skill from GitHub","tags":["Skills"],"description":"Clones a public GitHub repo, parses a `SKILL.md`, and creates a `DRAFT` skill owned by the caller. Authenticated. Body: `repoUrl` (required) plus optional `path` to the SKILL.md within the repo.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"The created DRAFT skill as a SkillSummary.","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string"}}},"platforms":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"latestVersion":{"type":"string"},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","slug","name","status"]}}}}}}},"/api/v1/skills/{slug}/publish":{"post":{"summary":"Publish a skill","tags":["Skills"],"description":"Publishes a draft skill after running the validation pipeline and AI quality/security review. Restricted to the author or an org `PUBLISHER`+. May move the skill to `PENDING_REVIEW` when AI flags a security issue, the author is untrusted, or AI review is unavailable; org-internal skills publish directly.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"The skill after publishing as a SkillSummary; status is PUBLISHED or PENDING_REVIEW depending on review outcome.","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"qualityScore":{"type":["number","null"]},"aiQualityScore":{"type":["number","null"]},"aiSecurityVerdict":{"type":["string","null"]},"latestVersion":{"type":"string"},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","slug","name","status"]}}}}}}},"/api/v1/skills/{slug}/composition":{"put":{"summary":"Set skill composition","tags":["Skills"],"description":"Defines a skill as an ordered composition of child skills (a workflow). Restricted to the author or an org `PUBLISHER`+. Child skills must be published; self-references and transitive cycles are rejected.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"The full SkillDetail after setting the composition (same shape as GET /skills/{slug}).","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"instructions":{"type":"string"},"isComposition":{"type":"boolean"},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"},"changelog":{"type":["string","null"]},"qualityScore":{"type":["number","null"]},"createdAt":{"type":"string"}}}},"composition":{"type":["object","null"],"properties":{"description":{"type":["string","null"]},"children":{"type":"array","items":{"type":"object","properties":{"skill":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"qualityScore":{"type":["number","null"]}}},"sortOrder":{"type":"integer"},"isParallel":{"type":"boolean"}}}}}},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["SCREENSHOT","YOUTUBE"]},"url":{"type":"string"},"caption":{"type":["string","null"]},"sortOrder":{"type":"integer"}}}}},"required":["id","slug","name","instructions","composition"]}}}}}},"delete":{"summary":"Remove skill composition","tags":["Skills"],"description":"Removes a skill's composition definition. Restricted to the author or an org `PUBLISHER`+. Returns `{ success: true }`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/{slug}/validate":{"get":{"summary":"Validate a skill","tags":["Skills"],"description":"Runs the validation pipeline (schema, content, structure, and security checks) against a skill's latest version and returns the report. Public for visible skills; `UNLISTED` skills can only be validated by their author.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"ValidationReport for the skill's latest version.","properties":{"slug":{"type":"string"},"qualityScore":{"type":"number"},"publishable":{"type":"boolean"},"checks":{"type":"object","properties":{"schema":{"type":"array","items":{"$ref":"#/$defs/check"}},"content":{"type":"array","items":{"$ref":"#/$defs/check"}},"structure":{"type":"array","items":{"$ref":"#/$defs/check"}},"security":{"type":"array","items":{"$ref":"#/$defs/check"}}}},"summary":{"type":"object","properties":{"errors":{"type":"integer"},"warnings":{"type":"integer"},"passed":{"type":"integer"},"total":{"type":"integer"}}}},"required":["slug","qualityScore","publishable","checks","summary"],"$defs":{"check":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"passed":{"type":"boolean"},"severity":{"type":"string","enum":["error","warning","info"]},"message":{"type":"string"}}}}}}}}}}},"/api/v1/skills/{slug}/feedback":{"post":{"summary":"Record skill execution feedback","tags":["Skills"],"description":"Records an execution outcome for a skill: `success` flag plus optional `rating`, `executionTimeMs`, `agentType`, and `source`. Optionally authenticated — anonymous feedback is accepted and attributed to no user.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"id":{"type":"string","description":"Created SkillFeedback id"}},"required":["ok","id"]}}}}}}},"/api/v1/skills/{slug}/versions":{"get":{"summary":"List skill versions","tags":["Skills"],"description":"Returns up to 100 versions of a skill, newest first, each with changelog, content hash, and quality score. Public for visible skills; `PRIVATE`/`ORG` skills require an authorized viewer.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","description":"Up to 100 versions, newest first.","items":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"},"changelog":{"type":["string","null"]},"contentHash":{"type":["string","null"]},"qualityScore":{"type":["number","null"]},"createdAt":{"type":"string"}},"required":["id","version","createdAt"]}}}}}}},"post":{"summary":"Create a skill version","tags":["Skills"],"description":"Publishes a new, higher semver version of a skill with updated instructions and optional changelog. Restricted to the author, an org `PUBLISHER`+, or an admin. Runs AI review; in orgs that gate modifications, a non-admin's version is held pending approval. Notifies installers of the update.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"The newly created version as a VersionSummary.","properties":{"id":{"type":"string"},"version":{"type":"string"},"changelog":{"type":["string","null"]},"contentHash":{"type":["string","null"]},"qualityScore":{"type":["number","null"]},"createdAt":{"type":"string"}},"required":["id","version","createdAt"]}}}}}}},"/api/v1/skills/{slug}/versions/{version}":{"get":{"summary":"Get a skill version","tags":["Skills"],"description":"Returns one version of a skill by its semver string, including full instructions. Public for visible skills; `PRIVATE`/`ORG` skills require an authorized viewer.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"version","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"},"instructions":{"type":"string"},"changelog":{"type":["string","null"]},"contentHash":{"type":["string","null"]},"qualityScore":{"type":["number","null"]},"createdAt":{"type":"string"}},"required":["id","version","instructions","createdAt"]}}}}}}},"/api/v1/skills/{slug}/versions/{from}/diff/{to}":{"get":{"summary":"Diff two skill versions","tags":["Skills"],"description":"Returns a unified diff of the instructions between two versions (`from` → `to`). Public for visible skills; `PRIVATE`/`ORG` skills require an authorized viewer. Public diffs are cached for one hour.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"from","required":true},{"schema":{"type":"string"},"in":"path","name":"to","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"fromVersion":{"type":"string"},"toVersion":{"type":"string"},"diff":{"type":"string","description":"Unified diff of the instructions."},"instructionsDiff":{"type":"string"},"from":{"type":"object","properties":{"version":{"type":"string"},"createdAt":{"type":"string"}}},"to":{"type":"object","properties":{"version":{"type":"string"},"createdAt":{"type":"string"}}},"changelog":{"type":["string","null"]},"hashChanged":{"type":"boolean"}},"required":["fromVersion","toVersion","diff","hashChanged"]}}}}}}},"/api/v1/skills/{slug}/versions/{version}/files":{"get":{"summary":"List a skill version's file tree","tags":["Skills"],"description":"Returns the multi-file manifest for a published skill version: `relativePath`, `bytes`, `lines`, and `sha256` per file. Public, but honors the skill's visibility (`PRIVATE`/`UNLISTED` require the requester to have access). Returns `404` for versions synced before multi-file ingest landed (fall back to the version's `instructions` field).","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"version","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"type":"object","properties":{"relativePath":{"type":"string"},"bytes":{"type":"integer"},"lines":{"type":"integer"},"sha256":{"type":"string"}},"required":["relativePath","bytes","lines","sha256"]}}},"required":["files"]}}}}}}},"/api/v1/skills/{slug}/versions/{version}/files/{*}":{"get":{"summary":"Get a single file from a skill version","tags":["Skills"],"description":"Returns the content of one file within a published skill version, keyed by the relative path captured after `files/` (nested paths allowed). Public, honors skill visibility, and rejects path-traversal attempts with `400 INVALID_PATH`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"version","required":true},{"schema":{"type":"string"},"in":"path","name":"*","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/skills/{slug}/reviews":{"get":{"summary":"List reviews for a skill","tags":["Reviews"],"description":"Returns a cursor-paginated list of reviews for the skill, newest first, including rating, helpful vote counts, and any author response. Public; authentication is optional and, when present, includes the caller's own vote on each review. `limit` max 50.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"rating":{"type":"integer"},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"usedFor":{"type":["string","null"]},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}},"required":["username","avatarUrl"]},"helpfulCount":{"type":"integer"},"notHelpfulCount":{"type":"integer"},"userVote":{"type":["boolean","null"]},"response":{"type":["object","null"],"properties":{"body":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["body","createdAt"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","rating","title","body","usedFor","author","helpfulCount","notHelpfulCount","userVote","response","createdAt","updatedAt"]}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["data","cursor","hasMore"]}}}}}},"post":{"summary":"Create a skill review","tags":["Reviews"],"description":"Creates a review (rating, title, body, optional `usedFor`) for a skill and notifies the author. Requires authentication. Users cannot review their own skill and may leave only one review per skill.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"rating":{"type":"integer"},"title":{"type":["string","null"]},"body":{"type":["string","null"]},"usedFor":{"type":["string","null"]},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}},"required":["username","avatarUrl"]},"helpfulCount":{"type":"integer"},"notHelpfulCount":{"type":"integer"},"userVote":{"type":["boolean","null"]},"response":{"type":["object","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","rating","title","body","usedFor","author","helpfulCount","notHelpfulCount","userVote","response","createdAt","updatedAt"]}}}}}}},"/api/v1/skills/{slug}/reviews/stats":{"get":{"summary":"Get review rating stats","tags":["Reviews"],"description":"Returns aggregate rating statistics for a skill: average rating, total review count, and the 1-5 star distribution. Public.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"avgRating":{"type":"number"},"totalReviews":{"type":"integer"},"distribution":{"type":"object","additionalProperties":{"type":"integer"},"description":"Map of star rating (1-5) to count"}},"required":["avgRating","totalReviews","distribution"]}}}}}}},"/api/v1/skills/reviews/{id}":{"patch":{"summary":"Update a review","tags":["Reviews"],"description":"Updates the caller's own review; changing the rating recomputes the skill's average rating. Requires authentication. Only the review author may edit it.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}},"delete":{"summary":"Delete a review","tags":["Reviews"],"description":"Deletes the caller's own review and recomputes the skill's rating counters. Requires authentication. Only the review author may delete it.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/reviews/{id}/vote":{"post":{"summary":"Vote a review helpful","tags":["Reviews"],"description":"Records or updates the caller's helpful / not-helpful vote on a review (upsert, one vote per user). Requires authentication.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/reviews/{id}/response":{"post":{"summary":"Respond to a review","tags":["Reviews"],"description":"Adds or updates the skill author's public response to a review (one response per review). Requires authentication; only the skill's author may respond.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/{slug}/install":{"post":{"summary":"Record a skill installation","tags":["Skills"],"description":"Records an install event and increments the skill's install counter. Optionally authenticated — authenticated installs dedupe once per user, anonymous installs dedupe per IP for 24h. Enforces skill visibility and the caller's org install policy. Body accepts optional `version` and `platform`. Returns the skill `slug` and the `version` that was recorded (the requested version, or the latest published version when none was given).","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/{slug}/like":{"post":{"summary":"Toggle like on a skill","tags":["Skills"],"description":"Toggles the authenticated caller's like on a skill — likes it if not already liked, otherwise removes the like. Authenticated. Returns the new `{ liked, likeCount }`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"liked":{"type":"boolean","description":"New like state after the toggle."},"likeCount":{"type":"integer"}},"required":["liked","likeCount"]}}}}}}},"/api/v1/skills/{slug}/media":{"post":{"summary":"Add media to a skill","tags":["Skills"],"description":"Attaches a media item (image/video URL with optional caption) to a skill, up to 10 per skill. Restricted to the author or an org `PUBLISHER`+. URLs are validated and sanitized.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"The created media item.","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["SCREENSHOT","YOUTUBE"]},"url":{"type":"string"},"caption":{"type":["string","null"]},"sortOrder":{"type":"integer"}},"required":["id","type","url","sortOrder"]}}}}}}},"/api/v1/skills/{slug}/media/{id}":{"delete":{"summary":"Remove skill media","tags":["Skills"],"description":"Deletes one media item from a skill by `id`. Restricted to the author or an org `PUBLISHER`+. Returns `{ success: true }`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/skills/{slug}/media/reorder":{"put":{"summary":"Reorder skill media","tags":["Skills"],"description":"Sets the display order of a skill's media from the provided `mediaIds` array. Restricted to the author or an org `PUBLISHER`+. Returns `{ success: true }`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}},"required":["success"]}}}}}}},"/api/v1/search/":{"get":{"summary":"Search skills","tags":["Search"],"description":"Full-text search over published, public skills using a `tsvector` index, with cursor pagination. Public; org members can also surface their org-visible skills via `?org=`. Supports `q`, `category`, `platform`, `minScore`, `sdlcPhase`, `official`, and `sort` (including `relevance`).","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/search/suggestions":{"get":{"summary":"Get search suggestions","tags":["Search"],"description":"Returns autocomplete suggestions (`skills` and `tags`) for a query prefix. Public; requires `q` of at least 2 characters and is cached for 30 seconds.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"skills":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}}},"tags":{"type":"array","items":{"type":"string"}}},"required":["skills","tags"]}}}}}}},"/api/v1/search/semantic":{"get":{"summary":"Semantic skill search","tags":["Search"],"description":"Vector (pgvector) semantic search over published, public skills, ranked by cosine similarity; falls back to keyword search when embeddings are unavailable. Public. Params: `q` (required) and `limit` (1-100, default 20). Cached for 60 seconds.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Skills ranked by semantic similarity, in the same envelope as GET /search. Semantic ranking has no stable id-order, so `cursor` is always null and `hasMore` always false.","properties":{"data":{"type":"array","items":{"type":"object","description":"SkillSummary"}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["data","cursor","hasMore"]}}}}}}},"/api/v1/search/suggest-by-deps":{"post":{"summary":"Suggest skills by dependencies","tags":["Search"],"description":"Given a project's dependency names (e.g. from package.json), returns published, public skills whose tags match, ranked by number of matching tags. Public. Body: `deps` (1-100 names) and `limit` (1-50, default 10).","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Skills whose tags match the provided dependency names, ranked by number of matching tags, in the same envelope as GET /search.","properties":{"data":{"type":"array","items":{"type":"object","description":"SkillSummary"}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["data","cursor","hasMore"]}}}}}}},"/api/v1/categories/":{"get":{"summary":"List all categories","tags":["Catalog"],"description":"Returns every skill category ordered by sort order. Public; cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/categories/featured":{"get":{"summary":"Get the featured skill per category","tags":["Catalog"],"description":"Returns a map of category slug to its top-ranked published skill (by likes, then installs), with `null` for categories that have none. Public; results are cached for 5 minutes and served with a 60-second `Cache-Control`.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Map of category slug to its top-ranked skill summary, or null when the category has none.","additionalProperties":{"oneOf":[{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]}}},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"avgRating":{"type":["number","null"]},"reviewCount":{"type":"integer"},"latestVersion":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"org":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}},{"type":"null"}]}}}}}}}},"/api/v1/categories/{slug}":{"get":{"summary":"Get a category by slug","tags":["Catalog"],"description":"Returns one category by slug. Public; cached for 5 minutes. Responds `404` if the slug is unknown.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"icon":{"type":["string","null"]},"sortOrder":{"type":"integer"}},"required":["id","slug","name","sortOrder"]}}}}}}},"/api/v1/tags/":{"get":{"summary":"Search tags","tags":["Skills"],"description":"Returns tags for autocomplete, alphabetically ordered, each with its skill count. Public. Optional `q` filters by name substring; `limit` caps results (1-50, default 20).","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/orgs/":{"post":{"summary":"Create an organization","tags":["Organizations"],"description":"Creates a new organization and makes the caller its first `ADMIN`. Requires authentication and an active organization subscription (platform admins bypass the paywall). A user may belong to at most one organization, so this fails if the caller is already a member.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}},"get":{"summary":"List the caller's organizations","tags":["Organizations"],"description":"Returns every organization the authenticated caller belongs to, with their role, join date, onboarding status, and job role. Requires authentication.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/orgs/{slug}":{"get":{"summary":"Get organization detail","tags":["Organizations"],"description":"Returns the organization's profile, tier, policy mode, governance settings, member/skill/install counts, and the caller's role. Requires authentication and org membership (any role); non-members receive the same `404` as a nonexistent organization.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"githubOrg":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"currentUserRole":{"type":["string","null"],"enum":["ADMIN","PUBLISHER","MEMBER",null]},"tier":{"type":"string","enum":["free","team","business","enterprise"]},"policyMode":{"type":"string","enum":["OPEN","ALLOWLIST","BLOCKLIST"]},"governance":{"type":"object","properties":{"crossDepartmentSharing":{"type":"boolean"},"crossTeamSharing":{"type":"boolean"},"requireApprovalForNewSkills":{"type":"boolean"},"requireApprovalForModifications":{"type":"boolean"},"memberApprovalsAllowed":{"type":"boolean"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"patch":{"summary":"Update organization settings","tags":["Organizations"],"description":"Updates the organization's `name`, `description`, and/or `avatarUrl`. Requires the `ADMIN` org role. The change is recorded in the org audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"githubOrg":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"totalInstalls":{"type":"integer"},"currentUserRole":{"type":["string","null"],"enum":["ADMIN","PUBLISHER","MEMBER",null]},"tier":{"type":"string","enum":["free","team","business","enterprise"]},"policyMode":{"type":"string","enum":["OPEN","ALLOWLIST","BLOCKLIST"]},"governance":{"type":"object","properties":{"crossDepartmentSharing":{"type":"boolean"},"crossTeamSharing":{"type":"boolean"},"requireApprovalForNewSkills":{"type":"boolean"},"requireApprovalForModifications":{"type":"boolean"},"memberApprovalsAllowed":{"type":"boolean"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Delete an organization","tags":["Organizations"],"description":"Permanently deletes the organization. Its skills are detached and made `PRIVATE` rather than deleted. Requires the `ADMIN` org role. The deletion is recorded in the org audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/members":{"get":{"summary":"List organization members","tags":["Org Members & Invites"],"description":"Returns a cursor-paginated list of the org's members with their username, avatar, role, and join date. Supports a `q` query param to filter by username. Callable by any org `MEMBER` session or an org token carrying the `members:read` scope.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","PUBLISHER","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}}}}}},"/api/v1/orgs/{slug}/members/{userId}":{"patch":{"summary":"Change a member's role","tags":["Org Members & Invites"],"description":"Sets a member's org role to `MEMBER`, `PUBLISHER`, or `ADMIN`. Requires the `ADMIN` org role. Demoting the organization's last remaining admin is rejected. The change is recorded in the org audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","PUBLISHER","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Remove a member (or leave)","tags":["Org Members & Invites"],"description":"Removes a member from the organization. Requires the `ADMIN` org role, unless the caller is removing themselves (leaving the org). Removing the last remaining admin is rejected. Frees a billable seat and is recorded in the audit log as either `removed` or `left`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/invites":{"post":{"summary":"Invite a member","tags":["Org Members & Invites"],"description":"Creates a pending invite by username or email, optionally scoped to a department/team, and emails the invitee. Org `ADMIN`s may invite anywhere; a department or team admin may invite into their own unit. Granting a role above `MEMBER` requires org `ADMIN`. Subject to pending-invite and member-capacity limits; recorded in the audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"token":{"type":"string"},"inviteeUsername":{"type":["string","null"]},"inviteeEmail":{"type":["string","null"]},"role":{"type":"string","enum":["ADMIN","PUBLISHER","MEMBER"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","DECLINED","EXPIRED"]},"invitedBy":{"type":"string"},"department":{"type":["string","null"]},"team":{"type":["string","null"]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"get":{"summary":"List pending invites","tags":["Org Members & Invites"],"description":"Returns the organization's pending invites with invitee, role, inviter, target unit, and expiry. Invite tokens are omitted from the list (they are only returned when the invite is created). Requires the `ADMIN` org role.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"token":{"type":"string","description":"Empty in list responses; only returned on invite creation."},"inviteeUsername":{"type":["string","null"]},"inviteeEmail":{"type":["string","null"]},"role":{"type":"string","enum":["ADMIN","PUBLISHER","MEMBER"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","DECLINED","EXPIRED"]},"invitedBy":{"type":"string"},"department":{"type":["string","null"]},"team":{"type":["string","null"]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}}},"/api/v1/orgs/{slug}/invites/bulk":{"post":{"summary":"Invite a batch of members","tags":["Org Members & Invites"],"description":"Invites many people at once from a list of usernames/emails sharing one role and optional department/team target. Each identifier runs the full single-invite path; per-identifier failures are reported without sinking the batch, while a permission failure rejects the whole request. Same role/permission rules as the single-invite endpoint; recorded in the audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"sent":{"type":"integer"},"failed":{"type":"integer"},"results":{"type":"array","items":{"type":"object","properties":{"identifier":{"type":"string"},"status":{"type":"string","enum":["sent","failed"]},"error":{"type":"string"},"token":{"type":"string"}},"required":["identifier","status"]}}}}}}}}}},"/api/v1/orgs/{slug}/invites/{inviteId}":{"delete":{"summary":"Revoke a pending invite","tags":["Org Members & Invites"],"description":"Deletes a pending invite so its token can no longer be redeemed. Requires the `ADMIN` org role. Recorded in the org audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"inviteId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/skills":{"get":{"summary":"List the organization's skills","tags":["Org Registry"],"description":"Returns the org's `ORG`-visibility skills using the standard skill list filters and cursor pagination. Callable by any org `MEMBER` session or an org token carrying the `registry:read` scope; tokens receive the full org-wide catalog view.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]}}},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}},"qualityScore":{"type":["number","null"]},"aiQualityScore":{"type":["number","null"]},"aiSecurityVerdict":{"type":["string","null"]},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"userLiked":{"type":"boolean"},"avgRating":{"type":["number","null"]},"reviewCount":{"type":"integer"},"latestVersion":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isComposition":{"type":"boolean"},"org":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}}}}}},"/api/v1/orgs/{slug}/templates":{"get":{"summary":"List skill templates","tags":["Org Templates"],"description":"Returns the organization's reusable skill templates (name, description, category, platforms). Requires any org role (`MEMBER` or higher).","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"categorySlug":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"post":{"summary":"Create a skill template","tags":["Org Templates"],"description":"Creates a reusable skill template for the organization (name, optional description, category, platforms, and starter instructions). Requires the `PUBLISHER` org role or higher. Subject to the per-org template limit.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"categorySlug":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/templates/{id}":{"get":{"summary":"Get a skill template","tags":["Org Templates"],"description":"Returns a single skill template including its full `instructions` body. Requires any org role (`MEMBER` or higher).","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"categorySlug":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"}},"instructions":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"patch":{"summary":"Update a skill template","tags":["Org Templates"],"description":"Updates a skill template's name, description, category, platforms, and/or instructions. Requires the `PUBLISHER` org role or higher.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"categorySlug":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Delete a skill template","tags":["Org Templates"],"description":"Permanently deletes an organization skill template. Requires the `ADMIN` org role.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/templates/{id}/create-skill":{"post":{"summary":"Create a skill from a template","tags":["Org Templates"],"description":"Instantiates a new `ORG`-visibility skill from a template, letting the caller override name, description, category, platforms, instructions, and version. Instructions (from the request or the template) must be at least 50 characters. Requires the `PUBLISHER` org role or higher.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]}}},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}},"qualityScore":{"type":["number","null"]},"aiQualityScore":{"type":["number","null"]},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"userLiked":{"type":"boolean"},"avgRating":{"type":["number","null"]},"reviewCount":{"type":"integer"},"latestVersion":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isComposition":{"type":"boolean"},"org":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/github":{"post":{"summary":"Connect a GitHub organization","tags":["Organizations"],"description":"Links a GitHub organization to this org and imports its members. Requires the `ADMIN` org role, and the caller must also be an admin of the target GitHub organization (verified via their stored GitHub token).","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"connected":{"type":"boolean"},"membersAdded":{"type":"integer"}}}}}}}},"delete":{"summary":"Disconnect the GitHub organization","tags":["Organizations"],"description":"Unlinks the connected GitHub organization from this org, disabling further member sync. Requires the `ADMIN` org role.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/github/sync":{"post":{"summary":"Sync members from GitHub","tags":["Organizations"],"description":"Manually triggers a re-sync of members from the connected GitHub organization. Requires the `ADMIN` org role and a previously connected GitHub org.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"synced":{"type":"integer"},"added":{"type":"integer"}}}}}}}}},"/api/v1/orgs/{slug}/analytics":{"get":{"summary":"Get organization analytics","tags":["Organizations"],"description":"Returns aggregate org analytics such as total skills, total installs, and recently active members. Requires any org role (`MEMBER` or higher). Results are cached for 5 minutes.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"totalSkills":{"type":"integer"},"totalInstalls":{"type":"integer"},"activeMembers":{"type":"integer"},"skillsByCategory":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"},"count":{"type":"integer"}}}},"topSkills":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"installs":{"type":"integer"}}}},"recentInstalls":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"count":{"type":"integer"}}}},"byDepartment":{"type":"array","items":{"type":"object","properties":{"department":{"type":"string"},"members":{"type":"integer"},"skills":{"type":"integer"},"installs":{"type":"integer"},"activeMembers":{"type":"integer"}}}}}}}}}}}},"/api/v1/orgs/{slug}/policy":{"patch":{"summary":"Set the skill policy mode","tags":["Org Policy"],"description":"Sets the org's install-policy mode to `OPEN`, `ALLOWLIST`, or `BLOCKLIST`, which governs how policy entries are enforced when members install skills. Requires the `ADMIN` org role. Recorded in the audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"policyMode":{"type":"string","enum":["OPEN","ALLOWLIST","BLOCKLIST"]}}}}}}}},"get":{"summary":"List policy entries","tags":["Org Policy"],"description":"Returns the org's skill policy entries (allowlisted/blocklisted skills, plus any department- or team-scoped entries). Callable by any org `MEMBER` session or an org token carrying the `policy:read` scope.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"skill":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"department":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"team":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"department":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"post":{"summary":"Add a policy entry","tags":["Org Policy"],"description":"Adds a skill to the org's policy (its effect depends on the policy mode). Org-level entries require the `ADMIN` org role; department- or team-scoped entries are part of the governance preview and require a platform admin. Idempotent per scope; recorded in the audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"departmentId":{"type":["string","null"]},"teamId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/policy/{skillSlug}":{"delete":{"summary":"Remove a policy entry","tags":["Org Policy"],"description":"Removes a skill from the org's policy. The optional `department` and `team` query params select a scoped entry; without them the org-level entry is removed. Org-level removal requires the `ADMIN` org role; scoped removal is part of the governance preview and requires a platform admin. Recorded in the audit log.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"skillSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/structure":{"get":{"summary":"Get organization structure","tags":["Org Hierarchy"],"description":"Returns the org's full department and team hierarchy with member and skill counts, plus the caller's role in each unit. Requires org role `MEMBER` or higher.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"orgRole":{"type":"string","enum":["ADMIN","PUBLISHER","MEMBER"]},"departments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"myRole":{"type":["string","null"],"enum":["ADMIN","MEMBER",null]},"teams":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"myRole":{"type":["string","null"],"enum":["ADMIN","MEMBER",null]},"createdAt":{"type":"string","format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}}}}},"/api/v1/orgs/{slug}/governance":{"patch":{"summary":"Update organization governance settings","tags":["Org Hierarchy"],"description":"Updates the org's governance toggles: cross-department and cross-team sharing, whether new skills and modifications require approval, and whether non-admin members may resolve approvals. Requires org role `ADMIN`. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"crossDepartmentSharing":{"type":"boolean"},"crossTeamSharing":{"type":"boolean"},"requireApprovalForNewSkills":{"type":"boolean"},"requireApprovalForModifications":{"type":"boolean"},"memberApprovalsAllowed":{"type":"boolean"}}}}}}}}},"/api/v1/orgs/{slug}/approvals":{"get":{"summary":"List skill approval requests","tags":["Org Hierarchy"],"description":"Returns the org's skill approval requests, both the pending review queue and resolved history, with cursor-based pagination and an optional `status` filter. Requires org role `MEMBER` or higher.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"action":{"type":"string","enum":["CREATION","MODIFICATION"]},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"skill":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"requestedBy":{"type":"string"},"reviewedBy":{"type":["string","null"]},"summary":{"type":["string","null"]},"note":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"}}}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}}}}}},"/api/v1/orgs/{slug}/approvals/{approvalId}/approve":{"post":{"summary":"Approve a skill approval request","tags":["Org Hierarchy"],"description":"Approves a pending request: a creation publishes the skill within its org/department/team scope, while a modification promotes the held version to latest. The reviewer must be an org `ADMIN`, the skill's department admin, or (when member approvals are enabled) any member, and cannot review their own request. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"approvalId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"action":{"type":"string","enum":["CREATION","MODIFICATION"]},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"skill":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"requestedBy":{"type":"string"},"reviewedBy":{"type":["string","null"]},"summary":{"type":["string","null"]},"note":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/approvals/{approvalId}/reject":{"post":{"summary":"Reject a skill approval request","tags":["Org Hierarchy"],"description":"Rejects a pending skill approval request, leaving the skill unpublished or unchanged and recording the resolution in the permanent audit trail. Same reviewer rules as approve: org `ADMIN`, the skill's department admin, or any member when member approvals are enabled, and never your own request. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"approvalId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"action":{"type":"string","enum":["CREATION","MODIFICATION"]},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"skill":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"requestedBy":{"type":"string"},"reviewedBy":{"type":["string","null"]},"summary":{"type":["string","null"]},"note":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/onboarding":{"post":{"summary":"Complete member onboarding","tags":["Org Hierarchy"],"description":"Self-assigns the calling member to the chosen departments and teams (as `MEMBER`) and records their job role. Idempotent: re-running adds any missing memberships and refreshes the job role and onboarded timestamp. Requires org role `MEMBER`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"onboarded":{"type":"boolean","enum":[true]},"jobRole":{"type":["string","null"]}}}}}}}}},"/api/v1/orgs/{slug}/departments":{"post":{"summary":"Create a department","tags":["Org Hierarchy"],"description":"Creates a department in the organization. Requires org role `ADMIN`. Enforces the per-org department limit and a unique department slug. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"myRole":{"type":["string","null"],"enum":["ADMIN","MEMBER",null]},"teams":{"type":"array","items":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}":{"patch":{"summary":"Update a department","tags":["Org Hierarchy"],"description":"Updates a department's name and/or description. Requires org role `ADMIN`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"myRole":{"type":["string","null"],"enum":["ADMIN","MEMBER",null]},"teams":{"type":"array","items":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Delete a department","tags":["Org Hierarchy"],"description":"Deletes a department. Its department- and team-scoped skills fall back to org-wide visibility, and its scoped policy blocks are cascade-deleted. Requires org role `ADMIN`. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}/members":{"get":{"summary":"List department members","tags":["Org Hierarchy"],"description":"Lists the members of a department with their sub-org roles (`ADMIN` or `MEMBER`). Requires org role `MEMBER` or higher.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}}},"post":{"summary":"Add a department member","tags":["Org Hierarchy"],"description":"Adds an existing organization member to the department, identified by `username`, with role `ADMIN` or `MEMBER`. Requires department admin (or org `ADMIN`). The target must already belong to the organization. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}/members/{userId}":{"patch":{"summary":"Update a department member's role","tags":["Org Hierarchy"],"description":"Changes a department member's role (`ADMIN` or `MEMBER`). Requires department admin (or org `ADMIN`). Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Remove a department member","tags":["Org Hierarchy"],"description":"Removes a member from the department, also removing their memberships in that department's teams. Requires department admin (or org `ADMIN`); members may remove themselves. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}/teams":{"post":{"summary":"Create a team","tags":["Org Hierarchy"],"description":"Creates a team within a department. Requires department admin (or org `ADMIN`). Enforces the per-department team limit and a unique team slug. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"myRole":{"type":["string","null"],"enum":["ADMIN","MEMBER",null]},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}/teams/{teamSlug}":{"patch":{"summary":"Update a team","tags":["Org Hierarchy"],"description":"Updates a team's name and/or description. Requires team admin, or the parent department's admin, or org `ADMIN`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"teamSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"memberCount":{"type":"integer"},"skillCount":{"type":"integer"},"myRole":{"type":["string","null"],"enum":["ADMIN","MEMBER",null]},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Delete a team","tags":["Org Hierarchy"],"description":"Deletes a team. Its team-scoped skills fall back to department visibility, and its scoped policy blocks are cascade-deleted. Requires department admin (or org `ADMIN`). Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"teamSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}/teams/{teamSlug}/members":{"get":{"summary":"List team members","tags":["Org Hierarchy"],"description":"Lists the members of a team with their sub-org roles (`ADMIN` or `MEMBER`). Requires org role `MEMBER` or higher.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"teamSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}}},"post":{"summary":"Add a team member","tags":["Org Hierarchy"],"description":"Adds an existing organization member to the team, identified by `username`, with role `ADMIN` or `MEMBER`, auto-adding the parent department membership if needed. Requires team admin (or department admin / org `ADMIN`). The target must already belong to the organization. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"teamSlug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/orgs/{slug}/departments/{deptSlug}/teams/{teamSlug}/members/{userId}":{"patch":{"summary":"Update a team member's role","tags":["Org Hierarchy"],"description":"Changes a team member's role (`ADMIN` or `MEMBER`). Requires team admin (or department admin / org `ADMIN`). Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"teamSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"role":{"type":"string","enum":["ADMIN","MEMBER"]},"joinedAt":{"type":"string","format":"date-time"}}}}}}}},"delete":{"summary":"Remove a team member","tags":["Org Hierarchy"],"description":"Removes a member from the team. Requires team admin (or department admin / org `ADMIN`); members may remove themselves. Records an audit entry.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true},{"schema":{"type":"string"},"in":"path","name":"deptSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"teamSlug","required":true},{"schema":{"type":"string"},"in":"path","name":"userId","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/orgs/checkout":{"post":{"summary":"Start an organization subscription checkout","tags":["Billing"],"description":"Creates a Stripe Checkout session (subscription mode) for the org paywall and returns the hosted checkout URL. Optional body `{ plan: \"team\" | \"business\" }` selects the tier (defaults to `team`). Requires an authenticated user; rejected if the caller already has an active subscription or already belongs to an organization.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"checkoutUrl":{"type":["string","null"]}}}}}}}}},"/api/v1/orgs/subscription":{"get":{"summary":"Get organization subscription status","tags":["Billing"],"description":"Returns the caller's org paywall entitlement for the subscription screen: whether they are entitled to create/keep an org, their subscription status (`active` / `canceled` / null), whether they are a platform admin (admins bypass the paywall), whether billing is configured on this deployment, and the per-seat monthly price in cents. Requires an authenticated user.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"entitled":{"type":"boolean"},"status":{"type":["string","null"],"enum":["active","canceled",null]},"isAdmin":{"type":"boolean"},"billingConfigured":{"type":"boolean"},"seatPriceCents":{"type":"integer"}}}}}}}}},"/api/v1/invites/{token}/accept":{"post":{"summary":"Accept an organization invite","tags":["Org Members & Invites"],"description":"Accepts a pending invite by its token, joining the caller to the organization (and any department/team the invite targets). Requires authentication; the caller's account or email must match the invite. Fails if the invite is expired, already used, or if the caller already belongs to another organization.","parameters":[{"schema":{"type":"string"},"in":"path","name":"token","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/invites/{token}/decline":{"post":{"summary":"Decline an organization invite","tags":["Org Members & Invites"],"description":"Declines a pending invite by its token, marking it `DECLINED` so it can no longer be redeemed. Requires authentication; if the invite is bound to a specific user, only that user may decline it.","parameters":[{"schema":{"type":"string"},"in":"path","name":"token","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]}}}}}}}}},"/api/v1/skills/{slug}/report":{"post":{"summary":"Report a skill","tags":["Skills"],"description":"Submits a moderation report against a published skill with a reason and optional description. Requires authentication. Users cannot report their own skill or file duplicate reports, and daily and pending-report limits apply; a skill auto-flags for review once it accumulates 3 or more pending reports.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"skillSlug":{"type":"string"},"skillName":{"type":"string"},"reason":{"type":"string","enum":["MALICIOUS","SPAM","INAPPROPRIATE","COPYRIGHT","MISLEADING","OTHER"]},"description":{"type":"string"},"reporterUsername":{"type":"string"},"status":{"type":"string","enum":["PENDING","REVIEWED","DISMISSED"]},"createdAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","skillSlug","skillName","reason","reporterUsername","status","createdAt","resolvedAt"]}}}}}}},"/api/v1/ai/generate":{"post":{"summary":"Generate a full skill from a prompt","tags":["AI"],"description":"Authenticated. Uses AI to generate all skill fields (name, description, tags, instructions) from a natural-language `prompt`. Enforces a daily per-user generation quota — returns `429` once the cap is exceeded; only successful generations count against it.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"GeneratedSkill","properties":{"name":{"type":"string"},"description":{"type":"string"},"categorySlug":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"instructions":{"type":"string"}},"required":["name","description","categorySlug","platforms","tags","instructions"]}}}}}}},"/api/v1/ai/generate/stream":{"post":{"summary":"Stream skill generation with progress","tags":["AI"],"description":"Authenticated. Same as `POST /ai/generate` but streams progress events over Server-Sent Events. The daily per-user quota is enforced before SSE headers flush (surfacing as a clean `429`); only a run that reaches the `complete` stage counts against the quota.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Server-Sent Events stream (text/event-stream). Each `data:` frame is one JSON progress event; stages emit in order: fetching-examples, generating, refining, then complete (carrying the generated skill) or error (carrying a message).","properties":{"stage":{"type":"string","enum":["fetching-examples","generating","refining","complete","error"]},"data":{"type":"object","description":"Present only on the 'complete' event — the generated skill.","properties":{"name":{"type":"string"},"description":{"type":"string"},"categorySlug":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"instructions":{"type":"string"}}},"message":{"type":"string","description":"Present only on the 'error' event."}},"required":["stage"]}}}}}}},"/api/v1/ai/suggest":{"post":{"summary":"Suggest a single skill field","tags":["AI"],"description":"Authenticated. Uses AI to suggest a value for one field (`name`, `description`, or `tags`) given partial skill `context`.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string"}},"required":["value"]}}}}}}},"/api/v1/bundles/":{"post":{"summary":"Create a skill bundle","tags":["Bundles"],"description":"Creates a bundle owned by the authenticated user from a list of skill slugs; every skill must be published and public or the request is rejected. Authenticated. Returns the new bundle summary.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}},"get":{"summary":"List bundles","tags":["Bundles"],"description":"Returns bundles with cursor pagination, optionally filtered by `author` and sorted by newest or most installed. Public; cached for 60 seconds.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/bundles/featured":{"get":{"summary":"List featured bundles","tags":["Bundles"],"description":"Returns curated starter bundles flagged as featured, ordered by install count. Public; cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"skillCount":{"type":"integer"},"installCount":{"type":"integer"},"createdAt":{"type":"string"}},"required":["slug","name","description","author","skillCount","installCount","createdAt"]}}}}}}}},"/api/v1/bundles/{slug}":{"get":{"summary":"Get bundle detail","tags":["Bundles"],"description":"Returns one bundle by slug with its ordered list of skills. Public; cached for 60 seconds. Responds `404` if the slug is unknown.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"skillCount":{"type":"integer"},"installCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"skills":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"installCount":{"type":"integer"}},"required":["slug","name","description","installCount"]}}},"required":["slug","name","description","author","skillCount","installCount","createdAt","updatedAt","skills"]}}}}}},"patch":{"summary":"Update a bundle","tags":["Bundles"],"description":"Updates a bundle's name, description, or skill list (a new skill list replaces all existing entries). Authenticated; only the bundle's author may edit it. Returns the updated summary.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]}}},"skillCount":{"type":"integer"},"installCount":{"type":"integer"},"createdAt":{"type":"string"}},"required":["slug","name","description","author","skillCount","installCount","createdAt"]}}}}}},"delete":{"summary":"Delete a bundle","tags":["Bundles"],"description":"Deletes a bundle by slug. Authenticated; only the bundle's author may delete it.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/api/v1/skills/{slug}/security":{"get":{"summary":"Get latest security scan","tags":["Security Scans"],"description":"Returns the most recent security scan for a skill with its letter grade (`A`-`F`), score, and finding count. Public callers see summary data only; the skill's author or a platform admin also receives the detailed findings. Returns `null` if the skill has never been scanned.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":["object","null"],"description":"Latest security scan, or null if the skill has never been scanned. Public callers receive the summary only (no findings); the skill author or a platform admin also receives the findings array.","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"versionId":{"type":["string","null"]},"grade":{"type":"string","enum":["A","B","C","D","F"]},"score":{"type":"number"},"findingsCount":{"type":"integer"},"findings":{"type":"array","description":"Only present for the skill author or a platform admin.","items":{"type":"object","properties":{"pattern":{"type":"string"},"severity":{"type":"string","enum":["error","warning","info"]},"message":{"type":"string"},"matched":{"type":"boolean"}},"required":["pattern","severity","message","matched"]}},"scannedAt":{"type":"string","format":"date-time"}},"required":["id","skillId","versionId","grade","score","findingsCount","scannedAt"]}}}}}}},"/api/v1/skills/{slug}/security/scan":{"post":{"summary":"Trigger a security scan","tags":["Security Scans"],"description":"Runs the security pattern scanner against the skill's latest version and persists a graded result. Requires authentication; only the skill's author or a platform admin may trigger a scan.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"versionId":{"type":["string","null"]},"grade":{"type":"string","enum":["A","B","C","D","F"]},"score":{"type":"number"},"findingsCount":{"type":"integer"},"findings":{"type":"array","items":{"type":"object","properties":{"pattern":{"type":"string"},"severity":{"type":"string","enum":["error","warning","info"]},"message":{"type":"string"},"matched":{"type":"boolean"}},"required":["pattern","severity","message","matched"]}},"scannedAt":{"type":"string","format":"date-time"}},"required":["id","skillId","versionId","grade","score","findingsCount","findings","scannedAt"]}}}}}}},"/api/v1/skills/{slug}/security/history":{"get":{"summary":"Get security scan history","tags":["Security Scans"],"description":"Returns up to 50 past security scans for a skill, newest first. Public callers see grade, score, and finding count only; the skill's author or a platform admin also receives detailed findings.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"scans":{"type":"array","items":{"type":"object","description":"Public callers receive the summary only (no findings); the skill author or a platform admin also receives the findings array.","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"versionId":{"type":["string","null"]},"grade":{"type":"string","enum":["A","B","C","D","F"]},"score":{"type":"number"},"findingsCount":{"type":"integer"},"findings":{"type":"array","description":"Only present for the skill author or a platform admin.","items":{"type":"object","properties":{"pattern":{"type":"string"},"severity":{"type":"string","enum":["error","warning","info"]},"message":{"type":"string"},"matched":{"type":"boolean"}},"required":["pattern","severity","message","matched"]}},"scannedAt":{"type":"string","format":"date-time"}},"required":["id","skillId","versionId","grade","score","findingsCount","scannedAt"]}}},"required":["scans"]}}}}}}},"/api/v1/security-scan/patterns":{"get":{"summary":"List security scan patterns","tags":["Security Scans"],"description":"Returns the public security-scan methodology feed: every detection pattern's `id`, `label`, `severity`, `category`, and `message`, without exposing the underlying regex. Public. Powers the `/security` page.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer"},"patterns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"message":{"type":"string"},"severity":{"type":"string","enum":["error","warning","info"]},"category":{"type":"string","enum":["shell","exfiltration","prompt-injection","command-injection","secrets","fs-escape","ssrf","supply-chain","sql-injection","privilege-escalation","container-escape","deserialization","llm-specific","obfuscation"]}},"required":["id","label","message","severity","category"]}}},"required":["total","patterns"]}}}}}}},"/api/v1/skills/{slug}/bookmark":{"post":{"summary":"Bookmark or unbookmark a skill","tags":["Skills"],"description":"Authenticated. Toggles the current user's bookmark on the skill identified by `slug` — adds it if absent, removes it otherwise. Returns the resulting bookmark state.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"bookmarked":{"type":"boolean"}},"required":["bookmarked"]}}}}}}},"/api/v1/bookmarks/":{"get":{"summary":"List my bookmarked skills","tags":["Social"],"description":"Authenticated. Returns the current user's bookmarked skills, cursor-paginated (`limit` 1–100, default 20).","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/leaderboard/":{"get":{"summary":"Get the skills leaderboard","tags":["Social"],"description":"Public. Returns the top skills ranked by activity over the given `period` (`24h`, `7d` (default), `30d`, or `all`), up to `limit` results (1–50, default 10). Responses are cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/leaderboard/creators":{"get":{"summary":"Get the top creators leaderboard","tags":["Social"],"description":"Public. Returns the top skill creators ranked by activity over the given `period` (`24h`, `7d` (default), `30d`, or `all`), up to `limit` results (1–50, default 20). Responses are cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","description":"CreatorLeaderboardEntry","properties":{"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string"},"totalInstalls":{"type":"integer"},"skillCount":{"type":"integer"},"rank":{"type":"integer"}},"required":["username","trustLevel","totalInstalls","skillCount","rank"]}}}}}}}},"/api/v1/users/{username}/badges":{"get":{"summary":"Get a user's creator badges","tags":["Users & Profiles"],"description":"Public. Computes and returns the achievement badges earned by the user with the given `username`. Returns `404` if no such user exists. Responses are cached for 5 minutes.","parameters":[{"schema":{"type":"string"},"in":"path","name":"username","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","description":"Badge","properties":{"id":{"type":"string"},"label":{"type":"string"},"icon":{"type":"string"},"earnedAt":{"type":["string","null"],"description":"ISO datetime; omitted when the earning date is unknown."}},"required":["id","label","icon"]}}}}}}}},"/api/v1/skills/{slug}/evals":{"post":{"summary":"Trigger a skill eval run","tags":["Evaluations"],"description":"Runs a behavioral eval for a published skill by scoring its test cases against the latest completed sandbox outputs, then persists a graded result with pass rate and improvement. Requires authentication; only the skill's author may run evals. The skill must be published and have at least one test case.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"versionId":{"type":["string","null"]},"status":{"type":"string"},"passRate":{"type":["number","null"]},"improvement":{"type":["number","null"]},"totalCases":{"type":"integer"},"passedCases":{"type":"integer"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string"},"label":{"type":"string"},"input":{"type":"string"},"expectedOutput":{"type":["string","null"]},"withSkillOutput":{"type":["string","null"]},"withoutSkillOutput":{"type":["string","null"]},"passed":{"type":"boolean"},"similarity":{"type":"number"}},"required":["testCaseId","label","input","expectedOutput","withSkillOutput","withoutSkillOutput","passed","similarity"]}},"durationMs":{"type":["number","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","skillId","versionId","status","passRate","improvement","totalCases","passedCases","results","durationMs","createdAt"]}}}}}},"get":{"summary":"Get eval history","tags":["Evaluations"],"description":"Returns a skill's eval run history, newest first (`limit` 1-50, default 10). Public; the response is cached for 60 seconds.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"versionId":{"type":["string","null"]},"status":{"type":"string"},"passRate":{"type":["number","null"]},"improvement":{"type":["number","null"]},"totalCases":{"type":"integer"},"passedCases":{"type":"integer"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string"},"label":{"type":"string"},"input":{"type":"string"},"expectedOutput":{"type":["string","null"]},"withSkillOutput":{"type":["string","null"]},"withoutSkillOutput":{"type":["string","null"]},"passed":{"type":"boolean"},"similarity":{"type":"number"}},"required":["testCaseId","label","input","expectedOutput","withSkillOutput","withoutSkillOutput","passed","similarity"]}},"durationMs":{"type":["number","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","skillId","versionId","status","passRate","improvement","totalCases","passedCases","results","durationMs","createdAt"]}}}}}}}},"/api/v1/skills/{slug}/evals/latest":{"get":{"summary":"Get latest eval result","tags":["Evaluations"],"description":"Returns the most recent completed eval for a skill, including pass rate, improvement, and per-test-case results. Public; the response is cached for 60 seconds.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"skillId":{"type":"string"},"versionId":{"type":["string","null"]},"status":{"type":"string"},"passRate":{"type":["number","null"]},"improvement":{"type":["number","null"]},"totalCases":{"type":"integer"},"passedCases":{"type":"integer"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string"},"label":{"type":"string"},"input":{"type":"string"},"expectedOutput":{"type":["string","null"]},"withSkillOutput":{"type":["string","null"]},"withoutSkillOutput":{"type":["string","null"]},"passed":{"type":"boolean"},"similarity":{"type":"number"}},"required":["testCaseId","label","input","expectedOutput","withSkillOutput","withoutSkillOutput","passed","similarity"]}},"durationMs":{"type":["number","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","skillId","versionId","status","passRate","improvement","totalCases","passedCases","results","durationMs","createdAt"]}}}}}}},"/api/v1/notifications/":{"get":{"summary":"List user notifications","tags":["Notifications"],"description":"Returns the authenticated user's notifications, newest first, using cursor pagination (`limit` default 20, max 50). Authenticated.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/notifications/counts":{"get":{"summary":"Get notification counts","tags":["Notifications"],"description":"Returns the authenticated user's total and unread notification counts. Authenticated.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer"},"unread":{"type":"integer"}},"required":["total","unread"]}}}}}}},"/api/v1/notifications/{id}/read":{"post":{"summary":"Mark a notification as read","tags":["Notifications"],"description":"Marks one notification as read for the authenticated user. Authenticated; a no-op if the notification does not belong to the caller.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/api/v1/notifications/read-all":{"post":{"summary":"Mark all notifications as read","tags":["Notifications"],"description":"Marks all of the authenticated user's unread notifications as read. Authenticated.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}}}}},"/api/v1/users/{username}/follow":{"post":{"summary":"Follow or unfollow a user","tags":["Users & Profiles"],"description":"Authenticated. Toggles the current user's follow relationship with the target `username` — follows if not already following, unfollows otherwise. Returns the resulting follow state.","parameters":[{"schema":{"type":"string"},"in":"path","name":"username","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"following":{"type":"boolean"},"followerCount":{"type":"integer"}},"required":["following","followerCount"]}}}}}}},"/api/v1/users/{username}/followers":{"get":{"summary":"List a user's followers","tags":["Users & Profiles"],"description":"Public. Returns a cursor-paginated list of the users following the given `username` (`limit` 1–50, default 20).","parameters":[{"schema":{"type":"string"},"in":"path","name":"username","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"followerCount":{"type":"integer"}},"required":["username","followerCount"]}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["data","cursor","hasMore"]}}}}}}},"/api/v1/users/{username}/following":{"get":{"summary":"List who a user follows","tags":["Users & Profiles"],"description":"Public. Returns a cursor-paginated list of the users the given `username` follows (`limit` 1–50, default 20).","parameters":[{"schema":{"type":"string"},"in":"path","name":"username","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"username":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"followerCount":{"type":"integer"}},"required":["username","followerCount"]}},"cursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}},"required":["data","cursor","hasMore"]}}}}}}},"/api/v1/skills/{slug}/fork":{"post":{"summary":"Fork a skill","tags":["Skills"],"description":"Creates a `DRAFT` copy of a published skill owned by the caller, copying its latest instructions and tags and incrementing the source's fork count. Authenticated. Cannot fork private skills or your own skill. Responds `201` with the new skill's `slug` and `id`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}},"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"Slug of the new forked DRAFT skill."},"id":{"type":"string"}},"required":["slug","id"]}}}}}}},"/api/v1/industries/":{"get":{"summary":"List industries with skill counts","tags":["Catalog"],"description":"Returns every industry vertical along with its count of published, public skills. Public endpoint; response is cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/industries/featured":{"get":{"summary":"Get the featured skill per industry","tags":["Catalog"],"description":"Returns a map of industry slug to its top-ranked published skill (by likes, then installs), with `null` for industries that have none. Public; results are cached for 5 minutes and served with a 60-second `Cache-Control`.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Map of industry slug to its top-ranked skill summary, or null when the industry has none.","additionalProperties":{"oneOf":[{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]}}},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}},"qualityScore":{"type":["number","null"]},"aiQualityScore":{"type":["number","null"]},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"userLiked":{"type":"boolean"},"avgRating":{"type":["number","null"]},"reviewCount":{"type":"integer"},"latestVersion":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isComposition":{"type":"boolean"},"org":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}},{"type":"null"}]}}}}}}}},"/api/v1/industries/stats":{"get":{"summary":"Get aggregate industry stats","tags":["Catalog"],"description":"Returns the headline counters for the `/industries` hero band: total industries (excluding the `GENERAL` catch-all), total published skills, and stateful (memory-enabled) skills. Public; cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"totalIndustries":{"type":"integer"},"totalSkills":{"type":"integer"},"statefulSkills":{"type":"integer"}},"required":["totalIndustries","totalSkills","statefulSkills"]}}}}}}},"/api/v1/industries/{slug}/detail":{"get":{"summary":"Get industry landing-page detail","tags":["Catalog"],"description":"Returns a single composite payload for the dedicated industry landing page: top skill, recent skills, stateful and current samples, categories represented, and sibling industries. Public; cached for 5 minutes. Responds `404` if the slug is unknown.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"info":{"type":"object","properties":{"value":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}}},"skillCount":{"type":"integer"},"topSkill":{"oneOf":[{"type":"object","description":"Skill summary object (see /api/v1/industries/{slug}/skills items)."},{"type":"null"}]},"recent":{"type":"array","items":{"type":"object","description":"Skill summary object."}},"statefulSamples":{"type":"array","items":{"type":"object","description":"Skill summary object."}},"currentSamples":{"type":"array","items":{"type":"object","description":"Skill summary object."}},"categoriesWithCounts":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"count":{"type":"integer"}},"required":["slug","name","count"]}},"siblings":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"skillCount":{"type":"integer"}}}}},"required":["info","skillCount","topSkill","recent","statefulSamples","currentSamples","categoriesWithCounts","siblings"]}}}}}}},"/api/v1/industries/{slug}":{"get":{"summary":"Get an industry by slug","tags":["Catalog"],"description":"Returns the static metadata for one industry vertical. Public; cached for 5 minutes. Responds `404` if the slug is unknown.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","enum":["GENERAL","SOFTWARE","HEALTHCARE","FINANCE","LEGAL","MARKETING","ECOMMERCE","EDUCATION","GAMING","MEDIA","SCIENCE","GOVERNMENT","MANUFACTURING","REAL_ESTATE","HR","LOGISTICS"]},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}},"required":["value","slug","name","description"]}}}}}}},"/api/v1/industries/{slug}/skills":{"get":{"summary":"List skills in an industry","tags":["Catalog"],"description":"Returns published, public skills for an industry ranked by likes then installs, using cursor pagination (`cursor`, `limit` — default 20, max 100). Public; served with a 60-second `Cache-Control`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Cursor-paginated skills for an industry. Note: this endpoint uses items/nextCursor (not data/cursor/hasMore).","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"author":{"type":"object","properties":{"username":{"type":"string"},"avatarUrl":{"type":["string","null"]},"trustLevel":{"type":"string","enum":["NEW","ESTABLISHED","TRUSTED"]}}},"status":{"type":"string","enum":["DRAFT","PENDING_REVIEW","PUBLISHED","ARCHIVED"]},"visibility":{"type":"string"},"platforms":{"type":"array","items":{"type":"string"}},"permissions":{"type":"array","items":{"type":"string"}},"qualityScore":{"type":["number","null"]},"aiQualityScore":{"type":["number","null"]},"installCount":{"type":"integer"},"likeCount":{"type":"integer"},"userLiked":{"type":"boolean"},"avgRating":{"type":["number","null"]},"reviewCount":{"type":"integer"},"latestVersion":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isComposition":{"type":"boolean"},"org":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"]}}}}}}},"/api/v1/skills/recommended":{"get":{"summary":"Get personalized recommendations","tags":["Skills"],"description":"Returns personalized skill recommendations for the authenticated caller, combining collaborative filtering with tag-overlap similarity over their installed skills. Authenticated. `limit` (1-50, default 6) caps results; responses are per-user cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","description":"Recommended skills as SkillSummary objects (may be empty when the user has no installs).","items":{"type":"object","description":"SkillSummary"}}},"required":["data"]}}}}}}},"/api/v1/external-sources/":{"get":{"summary":"List external skill sources","tags":["Catalog"],"description":"Returns all registered external sources (upstream GitHub repos that publish `SKILL.md` files), ordered by skill count, each with its skill count, last-synced time, and sync status. Public; cached for 5 minutes.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/external-sources/{slug}":{"get":{"summary":"Get external source detail","tags":["Catalog"],"description":"Returns a single external source by slug, including its skill count, last-synced time, and sync status. Public; cached for 5 minutes. Responds `404` if the source does not exist.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"githubUrl":{"type":"string"},"avatarUrl":{"type":["string","null"]},"description":{"type":["string","null"]},"skillCount":{"type":"integer"},"lastSyncedAt":{"type":["string","null"]},"syncStatus":{"type":"string"}},"required":["slug","name","githubUrl","avatarUrl","description","skillCount","lastSyncedAt","syncStatus"]}}}}}}},"/api/v1/leads/":{"post":{"summary":"Submit a contact or marketing lead","tags":["Email & Digests"],"description":"Public. Captures a lead (`email` and `source` required; optional `name` and `message`), persists it, and emails a notification to the site owner. Returns the created lead with `201`.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/orgs/{slug}/registry":{"get":{"summary":"Get org registry config","tags":["Org Registry"],"description":"Returns the organization's private-registry configuration merged over defaults, plus the current plan tier. Authenticated; the caller must be a member of the organization.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"allowedDomains":{"type":"array","items":{"type":"string"}},"approvalWorkflow":{"type":"string","enum":["auto","admin-approval"]},"deprecationPolicy":{"type":"string","enum":["warn-only","block-install-after-N-days"]},"blockAfterDays":{"type":"integer"},"tier":{"type":"string"}},"required":["allowedDomains","approvalWorkflow","deprecationPolicy","tier"]}}}}}},"patch":{"summary":"Update org registry config","tags":["Org Registry"],"description":"Updates the organization's private-registry configuration. Authenticated; requires the organization `ADMIN` role and a Team or Enterprise plan. `blockAfterDays` is required when the deprecation policy blocks installs after N days.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"allowedDomains":{"type":"array","items":{"type":"string"}},"approvalWorkflow":{"type":"string","enum":["auto","admin-approval"]},"deprecationPolicy":{"type":"string","enum":["warn-only","block-install-after-N-days"]},"blockAfterDays":{"type":"integer"},"tier":{"type":"string"}},"required":["allowedDomains","approvalWorkflow","deprecationPolicy","tier"]}}}}}}},"/api/v1/orgs/{slug}/registry/manifest":{"get":{"summary":"List org private skills","tags":["Org Registry"],"description":"Returns a manifest of the organization's private and org-visibility skills with their latest version numbers. Authenticated; the caller must be a member and the org must be on a Team or Enterprise plan.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"org":{"type":"string"},"skills":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"version":{"type":"string"},"description":{"type":["string","null"]},"visibility":{"type":"string"},"updatedAt":{"type":"string"}},"required":["slug","name","version","description","visibility","updatedAt"]}}},"required":["org","skills"]}}}}}}},"/api/v1/orgs/{slug}/registry/export":{"post":{"summary":"Request a registry export bundle","tags":["Org Registry"],"description":"Prepares a self-hosted registry export and returns a job id, download URL, status, and expiry. Authenticated; requires the organization `ADMIN` role and a paid (Team or Enterprise) plan.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"downloadUrl":{"type":"string"},"status":{"type":"string","enum":["queued","ready"]},"expiresAt":{"type":"string"}},"required":["jobId","downloadUrl","status","expiresAt"]}}}}}}},"/api/v1/orgs/{slug}/registry/export/bundle":{"get":{"summary":"Download registry export bundle","tags":["Org Registry"],"description":"Streams the organization's export as a `tar.gz` archive (skills JSON, a ready-to-run `docker-compose.yml`, and a README) for self-hosting. Authenticated; requires the organization `ADMIN` role and a paid plan.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}},"/api/v1/users/me/email-prefs":{"get":{"summary":"Get my email preferences","tags":["Users & Profiles"],"description":"Authenticated. Returns the current user's email notification preferences, including their weekly-digest opt-in state.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"weeklyDigest":{"type":"boolean"},"versionUpdates":{"type":"boolean"},"reviews":{"type":"boolean"}},"required":["weeklyDigest","versionUpdates","reviews"]}}}}}},"patch":{"summary":"Update my email preferences","tags":["Users & Profiles"],"description":"Authenticated. Updates the current user's email notification preferences (e.g. weekly-digest opt-in) and returns the saved settings.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"weeklyDigest":{"type":"boolean"},"versionUpdates":{"type":"boolean"},"reviews":{"type":"boolean"}},"required":["weeklyDigest","versionUpdates","reviews"]}}}}}}},"/api/v1/email/unsubscribe":{"get":{"summary":"One-click email unsubscribe","tags":["Email & Digests"],"description":"Public. Unsubscribes a user from the weekly digest using the signed `token` from an email link and returns an HTML confirmation page. Returns `400` HTML when the token is missing, invalid, or expired.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}},"/api/v1/skills/{slug}/install-bundle":{"get":{"summary":"Get verified install bundle","tags":["Signing & Provenance"],"description":"Returns a published, public skill's version files plus its DSSE signature bundle, canonical content digest, signer identity, signing method, and SLSA level so the CLI can recompute the digest and verify the signature locally. Public. Non-public or unpublished slugs return `404`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"version":{"type":"string"},"contentDigest":{"type":"string"},"files":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"sha256":{"type":"string"},"contents":{"type":"string"}},"required":["path","sha256","contents"]}},"signatureBundle":{"type":["object","null"],"description":"DSSE envelope from Sigstore, or null if the version is unsigned."},"attestationUrl":{"type":["string","null"]},"signerIdentity":{"type":["string","null"]},"signingKeyId":{"type":["string","null"]},"signingMethod":{"type":"string","enum":["DISTRIBUTOR","UPSTREAM_PASSTHROUGH"]},"slsaLevel":{"type":"integer"}},"required":["slug","version","contentDigest","files","signatureBundle","attestationUrl","signerIdentity","signingKeyId","signingMethod","slsaLevel"]}}}}}}},"/api/v1/skills/{slug}/verify":{"post":{"summary":"Verify a skill content digest","tags":["Signing & Provenance"],"description":"Compares a caller-supplied SHA-256 digest against the latest signed version's canonical content digest and returns whether it matches, along with the signer identity. Public but strictly rate-limited (10 req/min/IP). Returns a mismatch reason (`not_found`, `unsigned`, or `digest_mismatch`) when it does not verify.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"signerIdentity":{"type":["string","null"]},"mismatchReason":{"type":["string","null"],"enum":["digest_mismatch","unsigned","not_found",null]}},"required":["ok","signerIdentity","mismatchReason"]}}}}}}},"/api/v1/health/":{"get":{"summary":"Deep readiness health check","tags":["System"],"description":"Public, unauthenticated. Probes the database (Prisma) and, if configured, Redis, returning per-dependency `status` and `latencyMs`. Responds `200` with `status: ok` when healthy, or `503` with `status: degraded` if a dependency fails. Wired as the App Runner health-check URL; responses are never cached and error internals are never disclosed.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}}}}}},"/api/v1/openapi.json":{"get":{"summary":"Get the OpenAPI 3.1 spec (audience-filtered)","tags":["API Docs"],"description":"Returns the live OpenAPI 3.1 JSON schema. Platform admins (with an admin bearer token) get the complete surface; all other callers get the public + organization API with admin/internal/preview endpoints omitted. `Vary: Authorization`, never cached. `503` if the schema is not yet ready.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"Live OpenAPI 3.1 document, audience-filtered (admins get the full surface; others get the public + org subset). Vary: Authorization, never cached.","properties":{"openapi":{"type":"string"},"info":{"type":"object"},"paths":{"type":"object"},"components":{"type":"object"},"tags":{"type":"array","items":{"type":"object"}},"x-tagGroups":{"type":"array","items":{"type":"object"}}}}}}}}}},"/mcp":{"post":{"summary":"Handle MCP JSON-RPC requests","tags":["MCP"],"description":"Public MCP Streamable HTTP endpoint (Model Context Protocol). Accepts JSON-RPC requests for the `skills-hub` tools, prompts, and resources, establishing a new session (returned via the `mcp-session-id` response header) or reusing an existing one. Callers may be anonymous or authenticated — a valid `Authorization` credential attaches an org principal so install-policy filtering is enforced.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","description":"JSON-RPC 2.0 response written by the MCP StreamableHTTP transport (reply.hijack()). Body carries the result of the invoked JSON-RPC method (tools/list, tools/call, prompts/list, prompts/get, resources/list). Content-Type is application/json or text/event-stream depending on negotiation; the mcp-session-id response header names the session.","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":["string","number","null"]},"result":{"type":"object","description":"Method-specific payload — e.g. { tools: [...] }, { prompts: [...] }, { resources: [...] }, or a tool-call result { content: [{ type: 'text', text: '...' }] }."}}}}}}}},"get":{"summary":"Open the MCP server-sent event stream","tags":["MCP"],"description":"Public. Opens the Server-Sent Events channel for server-initiated MCP messages on an existing session identified by the `mcp-session-id` header. Requires a prior `POST /mcp` to establish the session; returns `400` if the session is unknown.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally."}}},"delete":{"summary":"Close an MCP session","tags":["MCP"],"description":"Public. Terminates the MCP session named by the `mcp-session-id` header, closing its transport and freeing server resources. Always returns `{ ok: true }`, even for an unknown session.","responses":{"200":{"description":"Successful response. The returned fields are described in this endpoint's summary/description; typed per-field response schemas are being added incrementally.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}}}}}},"servers":[{"url":"https://api.skills-hub.ai","description":"Production"},{"url":"http://localhost:3001","description":"Local development"}],"security":[{"BearerAuth":[]},{"ApiKeyAuth":[]}],"tags":[{"name":"Skills","description":"Discover, publish, version, fork, and install skills."},{"name":"Search","description":"Keyword, semantic, and hybrid skill search."},{"name":"Catalog","description":"Categories, industries, and external skill sources."},{"name":"Bundles","description":"Curated multi-skill bundles."},{"name":"Reviews","description":"Skill reviews, ratings, and votes."},{"name":"Authentication","description":"Login, registration, OAuth, and sessions."},{"name":"Users & Profiles","description":"Your account, API keys, preferences, and public profiles."},{"name":"Notifications","description":"Per-user notifications."},{"name":"Social","description":"Follows, bookmarks, and leaderboards."},{"name":"Organizations","description":"Organization workspaces: create, update, settings, analytics."},{"name":"Org Members & Invites","description":"Members, roles, and invitations."},{"name":"Org Templates","description":"Reusable org skill templates."},{"name":"Org Hierarchy","description":"Departments, teams, approvals, and onboarding."},{"name":"Org Registry","description":"An organization's private skill registry."},{"name":"Org Policy","description":"Install policy (OPEN / ALLOWLIST / BLOCKLIST) and policy-as-code."},{"name":"Billing","description":"Organization subscription checkout and Stripe webhooks."},{"name":"Signing & Provenance","description":"Cosign/SLSA signing, verification, and install bundles."},{"name":"Security Scans","description":"Skill security scan results and grades."},{"name":"Evaluations","description":"Automated skill evaluations."},{"name":"AI","description":"AI-assisted generation and suggestions."},{"name":"MCP","description":"Model Context Protocol server endpoints."},{"name":"Email & Digests","description":"Weekly digest preferences, email unsubscribe, and lead capture."},{"name":"System","description":"Health, readiness, and usage metering."},{"name":"API Docs","description":"OpenAPI spec and this reference."}],"x-tagGroups":[{"name":"Public API","tags":["Skills","Search","Catalog","Bundles","Reviews"]},{"name":"Account","tags":["Authentication","Users & Profiles","Notifications","Social"]},{"name":"Organizations","tags":["Organizations","Org Members & Invites","Org Templates","Org Hierarchy","Org Registry"]},{"name":"Governance","tags":["Org Policy"]},{"name":"Billing","tags":["Billing"]},{"name":"Trust & Provenance","tags":["Signing & Provenance","Security Scans","Evaluations"]},{"name":"Integrations & System","tags":["AI","MCP","Email & Digests","System","API Docs"]}]}