Skillet
Browse
⌘K
Log inJoin
docs
  • What is Skillet?
  • Skills & kits
  • Install
  • Add skills
  • Approve updates
  • Publish a skill
  • Teams
  • Safety
  • Privacy
  • FAQ
  • API
  • CLI
  • MCP
  • Scanner
  • Skill.md
  • Versioning
  • What is Skillet?
  • Skills & kits
  • Install
  • Add skills
  • Approve updates
  • Publish a skill
  • Teams
  • Safety
  • Privacy
  • FAQ
  • API
  • CLI
  • MCP
  • Scanner
  • Skill.md
  • Versioning

API

The Skillet HTTP API: anonymous reads, token scopes, the error contract, caching, rate-limit headers, and what /api/v1 promises.


Skillet's registry is a JSON HTTP API. Every read is anonymous: no key, no signup, no rate-limit form. Writes need a bearer token whose class fixes its scopes.

bash
curl -s "https://skillet.md/api/v1/search?q=code+review"

That works right now, from anywhere, with no setup.

Reference

Per-endpoint parameters, sample responses, and status codes, generated from the OpenAPI document so they cannot drift from the API:

ResourceCovers
SkillsCatalog, detail, versions, file contents, scan verdicts
DiscoveryCross-catalog search, public activity feed
PeopleProfiles and the follow graph
KitsPublic kits and their members
RegistryToken identity, sync manifest, stats, moderation, MCP

Machine-readable description of every endpoint, with operation IDs and typed schemas:

https://skillet.md/openapi.json

It is OpenAPI 3.1 and is built from the same source the registry serves at https://registry.skillet.md/openapi.json, so the two can never disagree. Point a function-calling client straight at it.

Two origins

OriginServesMethodsCORS
https://skillet.md/api/v1Anonymous readsGET, HEAD, OPTIONSAccess-Control-Allow-Origin: *
https://registry.skillet.md/api/v1Everything, including writesAllAllowlisted origins, credentialed

Call the apex from a browser. It forwards no cookie and no Authorization header, which is exactly why it can answer *. The registry origin allows credentials, so it answers only allowlisted origins and a cross-site fetch from your page will fail there.

Send writes to the registry origin. The apex answers 405 with code: read_only_mirror.

Auth

A token's prefix determines what it may do. Scopes are fixed at mint; a token cannot widen its own grant.

PrefixClassScopesGet one
skillet_s_User sessionread, sync, publish, claimSign in on the web
skillet_d_Paired deviceread, syncskillet connect <code>
skillet_k_Kit keyread, sync (one kit)Settings → Kits
skillet_m_Hosted MCP linkreadSettings → Account
ScopeGrants
readPublic and self-owned skills, kits, and profiles
syncThe sync manifest and approved skill content for a paired device
publishNew skill versions and visibility changes
claimHandle claim and author key binding

Request the narrowest class that does the job. An integration that reads one kit should hold a kit key, not a session token.

Every token is self-serve. Sign in, and the class you need is one page away: a device token from skillet connect <code>, a kit key from Settings → Kits, an MCP link from Settings → Account. There is no application to fill in and no sales step.

The same scope list is published machine-readably as RFC 9728 protected-resource metadata, which is what a 401 points at in its WWW-Authenticate header:

https://skillet.md/.well-known/oauth-protected-resource

Skillet is an OAuth 2.0 resource server: it accepts RFC 6750 bearer tokens and publishes its scopes at the well-known path above. It does not run an authorization server, so there is no /authorize or /token endpoint and no /.well-known/oauth-authorization-server document. Tokens come from the site and the CLI.

bash
curl -s https://registry.skillet.md/api/v1/whoami \
  -H "Authorization: Bearer $SKILLET_TOKEN"

whoami answers {"authenticated": false} for an anonymous caller rather than 401, so it doubles as a credential check.

Pagination

List endpoints take limit and offset.

limitDefault 50 (24 on discover/*). Clamped to 1-100.
offsetZero-based. Clamped server-side; deep offsets are refused, not served slowly.
totalTotal matches ignoring pagination, in the response body.

Out-of-range values are clamped, never rejected, so a bad limit returns a page rather than a 400.

Caching

Two different contracts, depending on what you asked for.

ResponseHeadersWhy
Catalog and discovery readsCache-Control: public, max-age=60, s-maxage=60Content changes on publish; a minute is the staleness budget.
Version-scoped reads (/manifest, /versions/{hash}/*)Strong ETag, Cache-Control: no-cacheAddressed by content hash, so the body for a given hash is immutable. Revalidate, don't re-download.
bash
curl -s "https://skillet.md/api/v1/skills/shadcn/shadcn/manifest" \
  -H 'If-None-Match: "sha256:c57e3cc…"'
# HTTP/2 304

There is no webhook surface. To track new publishes, poll GET /discover/feed and page on offset.

Errors

Every failure is JSON. Never an HTML page, on any status.

json
{
  "error": "Skill not found",
  "code": "skill_not_found",
  "message": "Skill not found",
  "statusCode": 404,
  "docs": "https://skillet.md/docs/api#errors"
}
FieldUse
codeStable and machine-readable. Branch on this.
errorShort reason phrase. Kept for older clients.
messageFor humans and logs. Wording may change.
docsThe page that explains how to resolve it.
request_idPresent on 5xx. Quote it in a bug report.
StatusMeans
400Malformed request: bad parameter, missing field
401Missing, expired, or revoked token
403Valid token, insufficient scope
404No such resource, or not readable by this caller
405Write sent to the read-only apex mirror
410The skill is deprecated
422Well-formed but invalid, e.g. a slug that breaks the grammar
429Rate limited

A private skill and a nonexistent one both answer 404. That is deliberate: a 403 would confirm the skill exists.

A deprecated skill answers 410 with its sunset notice rather than disappearing, so a client that pinned it can say why it stopped:

json
{ "deprecated": true, "deprecation_message": "Superseded by shadcn/shadcn-v2." }

Rate limits

Three per-IP buckets, each a 60-second window. Roughly 2,000 ambient reads, 300 writes, and 60 heavy reads (bundle downloads, version diffs, MCP tool calls) per minute.

Read the budget off the response instead of hardcoding those numbers. Metered responses carry the IETF RateLimit header fields, in both the spelling the current draft defines and the one older clients parse:

HeaderExampleMeansAlways sent
RateLimit-Limit2000Requests permitted in the windowYes
RateLimit-Policy"ambient"; q=2000; w=60The bucket this request was charged to, and its quotaYes
RateLimit-Remaining1993Requests left in this windowUncached only
RateLimit-Reset47Seconds until the window resetsUncached only
RateLimit"ambient"; r=1993; t=47The same live state as a structured fieldUncached only
Retry-After47Seconds to waitOn 429

The last three describe your bucket, so they are sent only when the response is not shared-cacheable. Catalog and search answer public, s-maxage=60 and sit in a CDN edge cache, where one caller's remaining count would be served to every other caller for the next minute. A wrong number is worse than none, so it is withheld rather than guessed.

What that means in practice: pace against RateLimit-Policy, which is the same for everyone and always present. When you need your exact position in the window, read RateLimit-Remaining from any uncached response, or from the 429 itself, which is always sent no-store.

bash
curl -sI "https://skillet.md/api/v1/skills?limit=1" | grep -i ratelimit

Exceeding a bucket returns 429 with Retry-After. There is no key to apply for and no per-key quota; if a legitimate integration needs more, open an issue.

What /api/v1 promises

Additive changes ship without noticeNew fields appear on existing responses. Ignore what you don't recognize.
code values are stableOnce an error code is published it keeps its meaning.
Enums can gain membersTreat an unknown scanStatus or category as unrecognized, not as an error.
Breaking changes get a new prefix/api/v2. /api/v1 is not rewritten under you.
Removal is announced in headers firstDeprecation, then Sunset at least 90 days out. See Versioning.
Undocumented routes are not APIThe registry serves ~175 routes; the ones in /openapi.json are the supported surface. The rest are internal and may change or vanish.

Markdown instead of JSON

If you want the prose rather than the record, skip the API. Every page serves Markdown at its own URL:

bash
curl -s -H 'Accept: text/markdown' https://skillet.md/shadcn/shadcn
curl -s https://skillet.md/docs/api.md

For a skill, that returns the published SKILL.md verbatim — the artifact an agent actually loads.

MCP

The hosted MCP server exposes a user's own kit as tools over Streamable HTTP. Discovery manifest:

https://skillet.md/.well-known/mcp.json

MCP is off until the user enables it in Settings → Account, which mints a read-only skillet_m_ link. See MCP for per-client setup.

Discovery files

FileContains
/openapi.jsonOpenAPI 3.1 description of the public API
/llms.txtOrientation for agents: what this site is for and when to call it
/.well-known/mcp.jsonMCP server card: endpoint, transport, auth
/.well-known/agent-skills/index.jsonThe skills Skillet itself publishes, with SHA-256 digests
/.well-known/oauth-protected-resourceRFC 9728: the scopes this API accepts, and where to get a token
/.well-known/oauth-protected-resource/api/v1/mcpRFC 9728 for the MCP endpoint alone: read and nothing else
/sitemap.xmlEvery indexable URL

Limitations

  • Writes are not available on the apex mirror. Use the registry origin.
  • No webhooks. Poll GET /discover/feed.
  • Private skills are invisible to anonymous callers, including their existence.
  • No per-key quotas. Limits are per IP, and reported in the RateLimit-* headers above.
  • No OAuth authorization server. Bearer tokens are accepted and their scopes published (RFC 6750 + RFC 9728), but there is no authorization-code flow to integrate against.
  • The OpenAPI document describes the public surface, not every internal route. Device sync internals, moderation queues, and account routes are deliberately absent.
FAQCLI

On this page

  • Reference
  • Two origins
  • Auth
  • Pagination
  • Caching
  • Errors
  • Rate limits
  • What `/api/v1` promises
  • Markdown instead of JSON
  • MCP
  • Discovery files
  • Limitations
Skilletseasoned to taste
Get appStatsBlogDocs
    Star0