https://niaskills.com/api/v1
JSON over HTTPS. CORS is open for GET, so you can call it straight from a
browser. No key is needed to read.
The machine-readable description is an OpenAPI 3.1 document served at
/api/v1/openapi.json, and /api/v1 itself
returns an index of every endpoint.
Rate limits
| Caller | Limit |
|---|---|
| Anonymous | 60 requests / minute / IP |
| With an API key | 1000 requests / minute |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and
X-RateLimit-Reset. Over the limit you get 429 with a Retry-After header.
Keys are issued on request rather than self-served — open an
issue and we will send you one.
A key is shown once and stored only as a hash, so if you lose it we roll it
rather than recover it. Send it as Authorization: Bearer nsk_….
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /skills |
List and filter skills |
| GET | /skills/{owner}/{name} |
Full metadata, stats, README |
| GET | /skills/{owner}/{name}/manifest |
File list, hashes, version |
| GET | /skills/{owner}/{name}/download |
Redirect to the version tarball |
| GET | /skills/{owner}/{name}/comments |
Public comments |
| GET | /stats/{owner}/{name} |
Counters only — cheap and cacheable |
| GET | /search |
Full-text over name, description, README |
| GET | /topics, /agents |
Facets with counts |
| POST | /installs |
Install telemetry |
| POST | /votes |
Like / dislike / clear (browser only) |
| POST | /comments |
Post a comment (browser only) |
There are no accounts. Liking and commenting are anonymous, identified by a
first-party session cookie so that a vote can be changed and a comment can be
attributed to whoever wrote it. That cookie is what authorises the two POST
endpoints marked browser only — an API key does not, and never will: one key
casting one permanent vote is worse than no vote at all.
GET /skills
| Query | Values |
|---|---|
sort |
hot (default), trending, top, new |
topic |
topic slug |
agent |
claude-code, cursor, codex, antigravity, github-copilot, gemini-cli, windsurf, cline, amp, opencode, zed, kiro, trae |
q |
search string |
page |
1-based, default 1 |
limit |
1–100, default 20 |
curl "https://niaskills.com/api/v1/skills?sort=top&limit=2"
{
"data": [
{
"slug": "nia/html-to-figma",
"owner": "nia",
"name": "html-to-figma",
"displayName": "HTML → Figma",
"summary": "Convert an HTML mockup into native, editable Figma layers.",
"topics": ["design", "figma"],
"agents": ["claude-code", "cursor", "codex", "antigravity"],
"stats": { "installs": 0, "likes": 0, "dislikes": 0, "comments": 0 },
"updatedAt": "2026-08-15T00:00:00.000Z"
}
],
"page": 1,
"limit": 2,
"total": 1
}
GET /skills/{owner}/{name}/manifest
What the CLI resolves before downloading. Every file carries its git blob
SHA-1 — the same value git hash-object <file> prints — so an install can be
verified end to end against the registry commit.
{
"slug": "nia/html-to-figma",
"version": "1.0.0",
"commit": "5e7f020…",
"tarball": "https://niaskills.com/api/v1/skills/nia/html-to-figma/download?version=1.0.0",
"files": [{ "path": "SKILL.md", "size": 4213, "blob_sha": "…" }]
}
Caching
GET responses send ETag and Cache-Control: s-maxage=60. Send
If-None-Match and you will get a 304 that does not count against your rate
limit.
Errors
Always the same envelope, with the HTTP status set to match:
{ "error": { "code": "not_found", "message": "No skill nia/nope" } }
bad_request, not_found, rate_limited, unauthorized, forbidden,
internal.