API

Distribution operations

Archives and hosted marketplaces for tools that do not speak this API (unzip, Claude Code plugin marketplaces).

Archives and hosted marketplaces for tools that do not speak this API (unzip, Claude Code plugin marketplaces). Paths are relative to https://reuseforge.com/api/v1.

Operations in this area
OperationMethodPath
Download a version as a ZIP archiveGET/items/{owner}/{slug}/versions/{version}/archive.zip
Claude Code plugin marketplace of an ownerGET/marketplaces/{owner}.json

Download a version as a ZIP archive

GET /items/{owner}/{slug}/versions/{version}/archive.zip Enabled on reuseforge.com

All files of a version as one deterministic, store-only (uncompressed) ZIP, for tools that understand archives but not this API (unzip, Claude Code archive plugin sources, CI caches). The same version always yields byte-identical output, so its SHA-256 (X-Content-SHA256, also ItemVersion.archive_sha256 once known) can be pinned: entries are sorted by UTF-8 path bytes, timestamps are fixed to 1980-01-01 00:00:00, permissions are 0644 (0755 for files the publish manifest lists in executable), names are flagged UTF-8, there are no directory entries, extra fields or data descriptors.

layout selects the variant. plain (default) holds the published files at their paths. claude-plugin wraps a skill, prompt or mcp_server item into a Claude Code plugin (.claude-plugin/plugin.json, skills/<slug>/..., commands/<slug>.md or .mcp.json); other kinds answer 400. Each layout has its own digest.

Access is exactly that of get_version_bundle: free versions are open to everyone, paid versions return 402 payment_required with an order_hint until you are entitled. A version that has any non-preview file is never served partially: no entitlement means 402, not a smaller archive. A quarantined version answers 403 version_quarantined, as for get_version_bundle, whatever If-None-Match says. latest resolves like get_version. Content-Length and ETag (the quoted SHA-256) are exact, so If-None-Match revalidation answers 304. A yanked version still downloads and carries X-RF-Yanked: 1. A retracted free item answers 410; a retracted paid item stays downloadable for the accounts that bought it.

The archive is built from the version's files and its stored, validated publish manifest only: a file named reuseforge.json is ordinary content and never configures the plugin, and a version published without a manifest has no mcp section, so an mcp_server version cannot take the claude-plugin layout. The claude-plugin layout is refused (400) once the item's kind differs from the kind in the stored manifest. Names that would overwrite each other on a case-insensitive or normalising filesystem (SKILL.md and Skill.md, NFC and NFD spellings, a file that is also a directory) make the version unarchivable: 400, without a layout pointer.

Download a version as a ZIP archive: facts
PropertyValue
Operation IDget_version_archive
AuthenticationNone required. A token raises your rate limits and shows your private items.
Rate tierread: 60/min per IP anonymous, 600/min per token with a token
CachingSends an ETag; repeat with If-None-Match to get 304 Not Modified
Python SDKclient.get_version_archive(...)
JavaScript SDKclient.getVersionArchive(...)
CLIrf versions download --format zip
MCP toolnot exposed as a tool
Deploymentsreuseforge.com: enabled. Python node: not implemented (answers 501).

Parameters

Download a version as a ZIP archive: parameters
NameInTypeRequiredDescription
ownerpathstringyesHandle of the owning user or organization.
slugpathstringyesItem slug, unique per owner.
versionpathstringyesAn exact semantic version or latest.
layoutquerystring: plain, claude-pluginnoplain (default): the published files as they are. claude-plugin: a Claude Code plugin wrapping a skill, prompt or mcp_server item. Default "plain".
If-None-MatchheaderstringnoETag from an earlier response; a match returns 304 without a body.

Responses

Download a version as a ZIP archive: responses
StatusMeaningBody
200 OKThe archive.application/zip: string (binary)
304 Not ModifiedNot modified. Keeps ETag and X-Content-SHA256.no body
400The request is malformed (bad JSON, unknown or mistyped parameter, invalid cursor).Problem. Codes: invalid_request, invalid_json, invalid_parameter, invalid_cursor, idempotency_key_required
402The item is paid and the caller is not entitled. order_hint says exactly what to order.Problem. Codes: payment_required
403Authenticated, but not allowed. Most often a missing scope (insufficient_scope, with required_scopes), an exceeded spend limit, or a role on the owning account that is too low. Also version_quarantined (the security scan or a moderator blocked the version you asked for) and review_removed (a moderator removed your review).Problem. Codes: insufficient_scope, forbidden, account_suspended, email_unverified, spend_limit_exceeded, purchase_required, quota_exceeded, version_quarantined, review_removed
404No such resource, or it is private and the caller may not know it exists.Problem. Codes: not_found
410The resource existed and is permanently unavailable (retracted item, expired plan).Problem. Codes: gone, plan_expired
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -o invoice-extractor-1.4.0.zip 'https://reuseforge.com/api/v1/items/acme/invoice-extractor/versions/1.4.0/archive.zip'

Python

python
import reuseforge

client = reuseforge.Client()  # token from REUSEFORGE_TOKEN, or the file `rf login` wrote

archive = client.get_version_archive("acme/invoice-extractor", "1.4.0")
print(len(archive), "bytes")

JavaScript

javascript
import { ReuseForge } from '@reuseforge/sdk';

const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });

const archive = await client.getVersionArchive("acme/invoice-extractor", "1.4.0");
console.log(archive.byteLength, 'bytes');

CLI

bash
rf versions download --format zip acme/invoice-extractor 1.4.0

# rf versions download <item> [version] [options]
# all options: rf versions download --help

Response 200: the body is application/zip, not JSON.

Claude Code plugin marketplace of an owner

GET /marketplaces/{owner}.json Enabled on reuseforge.com

A hosted Claude Code plugin marketplace for one account. Add it with /plugin marketplace add https://reuseforge.com/api/v1/marketplaces/<owner>.json, then /plugin install <slug>@reuseforge-<owner>.

It lists the owner's public, free, active items of kind skill, prompt or mcp_server that have a latest non-yanked, non-prerelease, non-quarantined version. Retracted, archived, draft, private, unlisted and paid items never appear, and neither does a quarantined version (the entry falls back to the next stable release). Each entry's source is {source: archive, url, sha256}: the claude-plugin layout of get_version_archive for that exact version, pinned by its SHA-256, so Claude Code refuses a download that differs. An owner without matching items yields an empty plugins list; a handle that does not exist is 404. The marketplace name is reuseforge-<owner>. Entries whose plugin name would read as one of Anthropic's own are left out. A cold digest cache is filled for at most 8 versions per request; entries not pinned yet are omitted and X-ReuseForge-Marketplace-Pending reports how many, with a short cache lifetime so the list completes on the next fetch (a 304 repeats the header). A version whose build started and never finished is skipped for 15 minutes and given up after 3 attempts; a version that cannot be packaged is left out. At most 100 plugins are listed, most downloaded first; when more items qualify, X-ReuseForge-Marketplace-Truncated: 100 says so. Entries carry keywords (the item's tags, also repeated as tags).

Claude Code plugin marketplace of an owner: facts
PropertyValue
Operation IDget_marketplace
AuthenticationNone required. A token raises your rate limits and shows your private items.
Rate tierread: 60/min per IP anonymous, 600/min per token with a token
CachingSends an ETag; repeat with If-None-Match to get 304 Not Modified
Python SDKclient.get_marketplace(...)
JavaScript SDKclient.getMarketplace(...)
CLIrf marketplaces get
MCP toolnot exposed as a tool
Deploymentsreuseforge.com: enabled. Python node: not implemented (answers 501).

Parameters

Claude Code plugin marketplace of an owner: parameters
NameInTypeRequiredDescription
ownerpathstringyesHandle of the owning user or organization.
If-None-MatchheaderstringnoETag from an earlier response; a match returns 304 without a body.

Responses

Claude Code plugin marketplace of an owner: responses
StatusMeaningBody
200 OKThe marketplace document (the file Claude Code reads as marketplace.json).application/json: ClaudeMarketplace
304 Not ModifiedNot modified. Keeps ETag and X-ReuseForge-Marketplace-Pending.no body
404No such resource, or it is private and the caller may not know it exists.Problem. Codes: not_found
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl 'https://reuseforge.com/api/v1/marketplaces/acme.json'

Python

python
import reuseforge

client = reuseforge.Client()  # token from REUSEFORGE_TOKEN, or the file `rf login` wrote

result = client.get_marketplace("acme")
print(result["name"])

JavaScript

javascript
import { ReuseForge } from '@reuseforge/sdk';

const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });

const result = await client.getMarketplace("acme");
console.log(result.name);

CLI

bash
rf marketplaces get acme

# rf marketplaces get <owner>
# all options: rf marketplaces get --help

Response 200 OK:

json
{
  "name": "reuseforge-acme",
  "description": "Free skills, prompts and MCP servers published by acme on ReuseForge.",
  "owner": {
    "name": "Acme Inc.",
    "url": "https://reuseforge.com/app/acme"
  },
  "plugins": [
    {
      "name": "invoice-extractor",
      "source": {
        "source": "archive",
        "url": "https://reuseforge.com/api/v1/items/acme/invoice-extractor/versions/1.4.0/archive.zip?layout=claude-plugin",
        "sha256": "6bfa50e3d2e00c052b46abe51fff89346ac803e45771f76dcf6df1ab74cca5e1"
      },
      "description": "Extract line items and totals from invoice PDFs.",
      "version": "1.4.0",
      "category": "skill",
      "author": {
        "name": "Acme Inc."
      },
      "homepage": "https://reuseforge.com/app/acme/invoice-extractor",
      "license": "MIT",
      "keywords": [
        "invoices",
        "pdf"
      ]
    }
  ]
}