Skip to content
Denofy
Esc
  • Pages

    Browse all packages
  • Verified packages
  • New packages
  • Collections
  • Documentation
  • CLI reference
  • How verification works
  • Publish a skill
↑↓ to navigate · Enter to open

REST API

Public read-only API under /api/v1 — endpoints, parameters, example requests and responses, errors and rate limits.

The registry has a public, read-only JSON API. It is what the CLI uses, and you can use it for your own tools. No authentication is needed.

  • Base URL: https://denofy.com/api/v1
  • Responses are JSON (application/json) unless stated otherwise; timestamps are ISO 8601 in UTC.
  • Machine-readable description: /api/v1/openapi.json (OpenAPI 3.1, generated from the same schemas as this page).

Endpoints#

GET/api/v1/search

Lists public packages that have at least one checked version. Without q the result is the full catalogue in the chosen order.

ParameterInTypeDescription
qquerystringFree text. Prefix match on name, title, summary, tags, category and description (up to 8 words).
typequeryenumPackage type. One of: skill, rule, agents-md, subagent, command. Unknown values are ignored.
toolquery"claude-code" | "codex" | "cursor"Only packages that support this tool. One of: claude-code, codex, cursor. Unknown values are ignored.
categoryqueryenumCategory slug. One of: coding, testing, git, frontend, backend, devops, data, documentation, security, productivity, other. Unknown values are ignored.
verifiedquery"0" | "1" | "true" | "false"1 or true: only packages whose latest version is verified.
sortqueryenumSort order. Default: relevance with a query, otherwise downloads. trending ranks by installs in the last 7 days. One of: relevance, downloads, newest, updated, rating, trending. Unknown values are ignored.
pagequeryinteger (≥ 1)
default 1
Page number, starting at 1.
limitqueryinteger (1–100)
default 20
Results per page (1–100).
bash
curl "https://denofy.com/api/v1/search?q=commit&tool=cursor&verified=1"
200 One page of results.
json
{
  "total": 1,
  "page": 1,
  "limit": 20,
  "items": [
    {
      "name": "commit-helper",
      "title": "Commit Helper",
      "summary": "Writes Conventional Commit messages from the staged diff.",
      "type": "skill",
      "category": "git",
      "tags": [
        "git",
        "commits"
      ],
      "tools": [
        "claude-code",
        "codex",
        "cursor"
      ],
      "author": "octocat",
      "downloads": 1284,
      "rating": {
        "average": 4.6,
        "count": 12
      },
      "latestVersion": "1.3.0",
      "status": "verified",
      "riskLevel": "none",
      "updatedAt": "2026-10-01T09:30:00.000Z",
      "url": "https://denofy.com/p/commit-helper"
    }
  ]
}

Package details#

GET/api/v1/packages/{name}

Metadata of a package: README (description), repository, license, rating and the latest version with its verification status.

ParameterInTypeDescription
namerequiredpathstringPackage name (slug), e.g. commit-helper.
bash
curl https://denofy.com/api/v1/packages/commit-helper
200 The package.
json
{
  "name": "commit-helper",
  "title": "Commit Helper",
  "summary": "Writes Conventional Commit messages from the staged diff.",
  "description": "# Commit Helper\n\nReads the staged diff and proposes a commit message…",
  "type": "skill",
  "category": "git",
  "tags": [
    "git",
    "commits"
  ],
  "tools": [
    "claude-code",
    "codex",
    "cursor"
  ],
  "author": {
    "username": "octocat",
    "name": "The Octocat"
  },
  "repository": {
    "url": "https://github.com/octocat/skills",
    "path": "commit-helper",
    "branch": "main"
  },
  "license": "MIT",
  "icon": "https://denofy.com/api/media/icon/1f0c2b9e-mabc123.webp",
  "links": {
    "docs": "https://octocat.github.io/skills",
    "issues": "https://github.com/octocat/skills/issues"
  },
  "downloads": 1284,
  "favorites": 37,
  "followers": 21,
  "rating": {
    "average": 4.6,
    "count": 12
  },
  "latestVersion": "1.3.0",
  "status": "verified",
  "riskLevel": "none",
  "archived": false,
  "deprecated": null,
  "premium": null,
  "createdAt": "2026-06-12T08:00:00.000Z",
  "updatedAt": "2026-10-01T09:30:00.000Z",
  "url": "https://denofy.com/p/commit-helper"
}
404 The package does not exist, is private or was hidden by the moderators.
json
{
  "error": "Package \"nope\" not found"
}

List versions#

GET/api/v1/packages/{name}/versions

All versions, newest first, without the full verification report. Blocked versions are left out; yanked versions are included with yanked: true.

ParameterInTypeDescription
namerequiredpathstringPackage name (slug), e.g. commit-helper.
bash
curl https://denofy.com/api/v1/packages/commit-helper/versions
200 All versions.
json
{
  "name": "commit-helper",
  "latestVersion": "1.3.0",
  "versions": [
    {
      "name": "commit-helper",
      "type": "skill",
      "tools": [
        "claude-code",
        "codex",
        "cursor"
      ],
      "version": "1.3.0",
      "commitSha": "9f1c2e7d3b4a5c6d7e8f90a1b2c3d4e5f6a7b8c9",
      "gitRef": "v1.3.0",
      "changelog": "Support for scopes",
      "status": "verified",
      "riskLevel": "none",
      "yanked": false,
      "downloads": 311,
      "createdAt": "2026-10-01T09:30:00.000Z",
      "verifiedAt": "2026-10-01T09:30:04.000Z",
      "files": [
        {
          "path": "SKILL.md",
          "size": 167,
          "sha256": "84108285e5634549ce6cfeabf9ccc548b88b0ef4f9d3d721e847aa3132197e64"
        }
      ],
      "tarball": {
        "url": "https://denofy.com/api/v1/packages/commit-helper/versions/1.3.0/download",
        "sha256": "3b5d5c3712955042212316173ccf37be800ea6b9b4d2f3e6b3e1c3d2a1b0c9d8",
        "size": 742
      },
      "installTargets": {
        "claude-code": {
          "mode": "directory",
          "project": ".claude/skills/commit-helper",
          "global": ".claude/skills/commit-helper"
        },
        "codex": {
          "mode": "directory",
          "project": ".agents/skills/commit-helper",
          "global": ".codex/skills/commit-helper"
        },
        "cursor": {
          "mode": "skill-to-mdc",
          "project": ".cursor/rules",
          "global": null
        }
      },
      "summary": "All 8 checks passed.",
      "archived": false,
      "deprecated": null,
      "premium": null,
      "moderation": null
    }
  ]
}
404 The package does not exist, is private or was hidden by the moderators.
json
{
  "error": "Package \"nope\" not found"
}

Resolve a version#

GET/api/v1/packages/{name}/versions/{version}

Resolves latest, an exact version or a semver range and returns the version including the full verification report. This is what the CLI calls before downloading.

ParameterInTypeDescription
namerequiredpathstringPackage name (slug), e.g. commit-helper.
versionrequiredpathstringExact version (1.2.0), latest, or a URL-encoded semver range (%5E1.2.0 for ^1.2.0). Ranges resolve to the highest matching version that is not yanked or blocked.
bash
curl https://denofy.com/api/v1/packages/commit-helper/versions/%5E1.2.0
200 The resolved version with report.
json
{
  "name": "commit-helper",
  "type": "skill",
  "tools": [
    "claude-code",
    "codex",
    "cursor"
  ],
  "version": "1.3.0",
  "commitSha": "9f1c2e7d3b4a5c6d7e8f90a1b2c3d4e5f6a7b8c9",
  "gitRef": "v1.3.0",
  "changelog": "Support for scopes",
  "status": "verified",
  "riskLevel": "none",
  "yanked": false,
  "downloads": 311,
  "createdAt": "2026-10-01T09:30:00.000Z",
  "verifiedAt": "2026-10-01T09:30:04.000Z",
  "files": [
    {
      "path": "SKILL.md",
      "size": 167,
      "sha256": "84108285e5634549ce6cfeabf9ccc548b88b0ef4f9d3d721e847aa3132197e64"
    }
  ],
  "tarball": {
    "url": "https://denofy.com/api/v1/packages/commit-helper/versions/1.3.0/download",
    "sha256": "3b5d5c3712955042212316173ccf37be800ea6b9b4d2f3e6b3e1c3d2a1b0c9d8",
    "size": 742
  },
  "installTargets": {
    "claude-code": {
      "mode": "directory",
      "project": ".claude/skills/commit-helper",
      "global": ".claude/skills/commit-helper"
    },
    "codex": {
      "mode": "directory",
      "project": ".agents/skills/commit-helper",
      "global": ".codex/skills/commit-helper"
    },
    "cursor": {
      "mode": "skill-to-mdc",
      "project": ".cursor/rules",
      "global": null
    }
  },
  "summary": "All 8 checks passed.",
  "archived": false,
  "deprecated": null,
  "premium": null,
  "moderation": null,
  "report": {
    "verifierVersion": "1.1.0",
    "status": "verified",
    "riskLevel": "none",
    "checkedAt": "2026-10-16T17:54:30.832Z",
    "summary": "All 8 checks passed.",
    "checks": [
      {
        "id": "files.limits",
        "category": "structure",
        "level": "pass",
        "message": "1 files, 167 B — within size limits."
      },
      {
        "id": "skill.frontmatter",
        "category": "structure",
        "level": "pass",
        "message": "SKILL.md has valid YAML frontmatter.",
        "file": "SKILL.md"
      },
      {
        "id": "skill.name",
        "category": "structure",
        "level": "pass",
        "message": "`name` is valid (\"commit-helper\").",
        "file": "SKILL.md"
      },
      {
        "id": "skill.description",
        "category": "structure",
        "level": "pass",
        "message": "`description` is present.",
        "file": "SKILL.md"
      },
      {
        "id": "compat.claude-code",
        "category": "compatibility",
        "level": "pass",
        "message": "Installs correctly for Claude Code → .claude/skills/commit-helper."
      },
      {
        "id": "compat.codex",
        "category": "compatibility",
        "level": "pass",
        "message": "Installs correctly for OpenAI Codex → .agents/skills/commit-helper."
      },
      {
        "id": "compat.cursor",
        "category": "compatibility",
        "level": "pass",
        "message": "Installs correctly for Cursor → .cursor/rules."
      },
      {
        "id": "security.scan",
        "category": "security",
        "level": "pass",
        "message": "Security scan found no suspicious patterns."
      }
    ],
    "findings": [],
    "compatibility": [
      {
        "tool": "claude-code",
        "ok": true,
        "target": ".claude/skills/commit-helper",
        "issues": []
      },
      {
        "tool": "codex",
        "ok": true,
        "target": ".agents/skills/commit-helper",
        "issues": []
      },
      {
        "tool": "cursor",
        "ok": true,
        "target": ".cursor/rules",
        "issues": []
      }
    ],
    "files": [
      {
        "path": "SKILL.md",
        "size": 167,
        "sha256": "84108285e5634549ce6cfeabf9ccc548b88b0ef4f9d3d721e847aa3132197e64"
      }
    ],
    "stats": {
      "fileCount": 1,
      "totalSize": 167
    },
    "metadata": {
      "name": "commit-helper",
      "description": "Writes Conventional Commit messages from the staged diff."
    },
    "mainFile": "SKILL.md",
    "diff": null,
    "allowlist": null
  }
}
403 The version was blocked by the moderators and cannot be installed.
json
{
  "error": "commit-helper@1.2.0 was blocked by the Denofy moderators and cannot be installed."
}
404 The package or a matching version does not exist, is private or was hidden by the moderators.
json
{
  "error": "Package \"nope\" not found"
}

Download the tarball#

GET/api/v1/packages/{name}/versions/{version}/download

Streams the immutable .tgz of a version. Compare its sha256 with tarball.sha256 from the version endpoint (the CLI does this automatically). Each download is counted unless count=0 is passed. Premium packages (premium is set) need a license: send Authorization: Bearer <token> (from denofy login); the response is then a redirect to a signed link that is valid for 60 seconds.

ParameterInTypeDescription
namerequiredpathstringPackage name (slug), e.g. commit-helper.
versionrequiredpathstringExact version (1.2.0), latest, or a URL-encoded semver range (%5E1.2.0 for ^1.2.0). Ranges resolve to the highest matching version that is not yanked or blocked.
countquery"0" | "1"0: do not count this download (mirrors, tests).
Response headerDescription
x-denofy-versionResolved version
x-denofy-sha256sha256 of the tarball (hex)
x-denofy-commitGit commit the version was built from
x-denofy-statusVerification status
cache-controlpublic, max-age=31536000, immutable
bash
curl -LO https://denofy.com/api/v1/packages/commit-helper/versions/1.3.0/download
200 The tarball.application/gzip
302 Premium package with a valid license: redirect to a short-lived signed download link.
402 Premium package without a valid license (or without a token).
json
{
  "error": "commit-helper is a premium package and you have no valid license.",
  "code": "license_required",
  "purchaseUrl": "https://denofy.com/p/commit-helper#premium"
}
403 The version was blocked by the moderators.
json
{
  "error": "commit-helper@1.2.0 was blocked by the Denofy moderators and cannot be installed."
}
404 The package or version does not exist, is private or was hidden by the moderators.
json
{
  "error": "Package \"nope\" not found"
}
410 The tarball is missing from storage.
json
{
  "error": "Tarball is missing from storage"
}

README badge#

GET/api/v1/packages/{name}/badgenot rate limited

SVG badge with the verification status and latest version. Not rate limited (GitHub fetches badges through a few proxy IPs). Cached for 5 minutes; unknown packages get a grey "not found" badge with status 404, cached for 1 minute.

ParameterInTypeDescription
namerequiredpathstringPackage name (slug), e.g. commit-helper.
bash
curl https://denofy.com/api/v1/packages/commit-helper/badge
200 SVG badge.image/svg+xml
404 SVG badge "not found".image/svg+xml

Errors#

Errors use a JSON body with a human-readable message:

json
{ "error": "Package \"nope\" not found" }
StatusMeaning
400Malformed request.
402Premium package: a license is needed (see purchaseUrl).
403The version was blocked by the Denofy moderators.
404Package or version not found (also private and hidden packages).
410The tarball is gone from storage (please report it).
429Rate limit exceeded (300 requests per 60 s and IP by default). Wait for Retry-After seconds.
500Unexpected server error.
503Temporarily unavailable (database down or maintenance).

Rate limits#

All /api/v1 endpoints except the badge are limited to 300 requests per 60 seconds and IP by default (fixed windows; a self-hosted instance can change this with RATE_LIMIT_API_IP). Every response carries the current state:

HeaderDescription
x-ratelimit-limitRequests allowed in the current window.
x-ratelimit-remainingRequests left in the current window.
retry-afterOnly on 429: seconds until the window resets.

When the limit is exceeded the API answers 429:

json
{ "error": "Too many requests. Try again in 42 seconds.", "retryAfter": 42 }

Wait for Retry-After seconds before the next request. The CLI waits once automatically for short limits (up to 10 seconds) and otherwise prints how long to wait. Other limits of the platform:

LimitDefault
REST API (/api/v1, CLI) per IP300 per 1 min
Sign-in attempts per IP10 per 10 min
New packages per user10 per 1 h
New packages per IP20 per 1 h
Syncs and re-verifications per user30 per 1 h
Syncs per package (manual and webhook)10 per 1 h
Reviews per user10 per 1 h
Reviews per IP30 per 1 h
Reports per user10 per 1 h
Reports per IP20 per 1 h
Follows and unfollows per user60 per 1 h
Favourites per user60 per 1 h
Collection changes per user30 per 1 h
Maintainer invitations per user20 per 1 h
Checkouts started per user10 per 1 h
Checkouts started per IP20 per 1 h
Verification e-mails per user5 per 1 h
Data exports per user5 per 1 h
Image uploads per user30 per 1 h
CLI sign-in requests per IP20 per 1 h

Versioning of the API#

/api/v1 only gets backwards-compatible changes: new fields and new endpoints. Clients should ignore unknown fields. Breaking changes would get a new prefix.

Example: install without the CLI#

bash
# 1. resolve the version and read the tarball hash
curl -s https://denofy.com/api/v1/packages/commit-helper/versions/latest \
  | jq -r '.tarball.url, .tarball.sha256'

# 2. download and verify
curl -sLo pkg.tgz https://denofy.com/api/v1/packages/commit-helper/versions/1.3.0/download
echo "<sha256>  pkg.tgz" | sha256sum -c -

# 3. extract into the tool folder (the tarball has one top-level folder)
mkdir -p .claude/skills/commit-helper
tar -xzf pkg.tgz -C .claude/skills/commit-helper --strip-components=1
Edit this page on GitHub