API
Items operations
Search, publish and manage items.
Search, publish and manage items. Paths are relative to https://reuseforge.com/api/v1.
| Operation | Method | Path |
|---|---|---|
| Search and list items | GET | /items |
| Create an item | POST | /items |
| Get an item | GET | /items/{owner}/{slug} |
| Update an item | PATCH | /items/{owner}/{slug} |
| Retract an item | DELETE | /items/{owner}/{slug} |
| Star an item | PUT | /items/{owner}/{slug}/star |
| Remove your star | DELETE | /items/{owner}/{slug}/star |
| Item statistics | GET | /items/{owner}/{slug}/stats |
Search and list items
GET /items Enabled on reuseforge.com
Full-text search (when q is given) and filtered listing of public, active items. Signed-in callers also see their own private and unlisted items when owner names themselves or an organization they belong to. Default sort is relevance with q and trending without.
| Property | Value |
|---|---|
| Operation ID | search_items |
| Authentication | None required. A token raises your rate limits and shows your private items. |
| Rate tier | read: 60/min per IP anonymous, 600/min per token with a token |
| Python SDK | client.search_items(...) |
| JavaScript SDK | client.searchItems(...) |
| CLI | rf items search |
| MCP tool | search_items |
| Deployments | reuseforge.com: enabled. Python node: implemented. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | no | Search text. Matches title, summary, tags, capabilities and owner. |
kind | query | array of ItemKind | no | Restrict to these kinds (comma separated). |
capability | query | array of string | no | Capability ids from the planner taxonomy (comma separated, all must match). |
tag | query | string | no | |
license | query | array of string | no | SPDX identifier (comma separated for any-of). |
max_price_cents | query | integer | no | Only items priced at or below this many cents. |
free_only | query | boolean | no | Default false. |
verified | query | boolean | no | When true, only items whose latest version has a passing verification. |
min_rating | query | number | no | |
owner | query | string | no | Owner handle (user or organization). |
sort | query | ItemSort | no | |
cursor | query | string | no | Opaque cursor from the previous page's next_cursor. |
limit | query | integer | no | Page size. Default 30. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 OK | A page of items. readme and viewer are omitted in lists. | application/json: ItemPage |
| 400 | The request is malformed (bad JSON, unknown or mistyped parameter, invalid cursor). | Problem. Codes: invalid_request, invalid_json, invalid_parameter, invalid_cursor, idempotency_key_required |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl 'https://reuseforge.com/api/v1/items?q=invoice%20pdf%20extraction'Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
for entry in client.search_items(q="invoice pdf extraction"): # iterating fetches further pages on demand
print(entry["full_name"])JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
for await (const entry of client.searchItems({ q: "invoice pdf extraction" })) { // iterating fetches further pages on demand
console.log(entry.full_name);
}CLI
rf items search 'invoice pdf extraction'
# rf items search [query]... [options]
# all options: rf items search --helpResponse 200 OK:
{
"data": [
{
"id": "itm_invoiceextr2",
"object": "item",
"owner": {
"id": "acc_acmelabsorg2",
"type": "org",
"handle": "acme",
"display_name": "Acme Labs",
"verified": true,
"avatar_url": ""
},
"slug": "invoice-extractor",
"full_name": "acme/invoice-extractor",
"kind": "skill",
"title": "Invoice extractor",
"summary": "Extracts vendor, totals and line items from PDF invoices into JSON using layout-aware OCR.",
"visibility": "public",
"status": "active",
"license": "MIT",
"pricing_model": "free",
"price_cents": 0,
"currency": "USD",
"source": {
"provider": "github",
"url": "https://github.com/acme/invoice-extractor",
"ref": "acme/invoice-extractor"
},
"homepage_url": "https://acme.example/invoice-extractor",
"html_url": "https://reuseforge.com/app/acme/invoice-extractor",
"capabilities": [
"document-parsing",
"data-analysis"
],
"tags": [
"pdf",
"invoices",
"ocr"
],
"latest_version": "1.4.0",
"verification": {
"state": "passed",
"version": "1.4.0",
"tests_pass_rate": 0.97,
"verified_at": "2026-10-28T09:12:40Z"
},
"stats": {
"stars": 412,
"downloads": 9120,
"reviews": 18,
"sales": 0
},
"signals": {
"stars": 1860,
"downloads": 9120,
"tests_pass_rate": 0.97,
"forks": 143,
"open_issues": 12,
"days_since_update": 6
},
"rating": 4.6,
"rating_count": 18,
"demo": false,
"forked_from": null,
"project_id": null,
"created_at": "2026-03-02T14:05:11Z",
"updated_at": "2026-10-28T09:10:02Z"
},
{
"id": "itm_ragharness22",
"object": "item",
"owner": {
"id": "acc_janedoeuser2",
"type": "user",
"handle": "janedoe",
"display_name": "Jane Doe",
"verified": false,
"avatar_url": "https://avatars.githubusercontent.com/u/1000001"
},
"slug": "invoice-rag-harness",
"full_name": "janedoe/invoice-rag-harness",
"kind": "harness",
"title": "Invoice RAG harness",
"summary": "Agent harness that indexes invoices, answers spend questions with citations and exports a dashboard.",
"visibility": "public",
"status": "active",
"license": "Commercial-Single-Project",
"pricing_model": "fixed",
"price_cents": 1200,
"currency": "USD",
"source": {
"provider": "manual",
"url": "",
"ref": ""
},
"homepage_url": "",
"html_url": "https://reuseforge.com/app/janedoe/invoice-rag-harness",
"capabilities": [
"retrieval-rag",
"llm-chat",
"data-analysis"
],
"tags": [
"rag",
"invoices",
"dashboard"
],
"latest_version": "0.9.2",
"verification": {
"state": "passed",
"version": "0.9.2",
"tests_pass_rate": 0.91,
"verified_at": "2026-10-30T16:41:05Z"
},
"stats": {
"stars": 37,
"downloads": 64,
"reviews": 3,
"sales": 11
},
"signals": {
"stars": 37,
"downloads": 64,
"tests_pass_rate": 0.91,
"days_since_update": 4
},
"rating": 4.3,
"rating_count": 3,
"demo": false,
"forked_from": null,
"project_id": null,
"created_at": "2026-09-12T08:00:00Z",
"updated_at": "2026-10-30T16:40:12Z"
}
],
"next_cursor": "eyJvIjoyLCJzIjoicmVsZXZhbmNlIn0",
"has_more": true,
"total": 37
}Create an item
POST /items Enabled on reuseforge.com
Creates an item (metadata only). Publish content with publish_version. New items are draft until their first version is published unless the item only points at an external source. Paid items require a verified email and a payout address. owner defaults to you; set it to an organization handle you have write role on.
| Property | Value |
|---|---|
| Operation ID | create_item |
| Authentication | Bearer token holding items:write |
| Rate tier | write: not allowed anonymous, 120/min per token with a token |
| Idempotency | Idempotency-Key header, optional. The SDKs and the CLI send one for you. |
| Python SDK | client.create_item(...) |
| JavaScript SDK | client.createItem(...) |
| CLI | rf items create |
| MCP tool | create_item |
| Deployments | reuseforge.com: enabled. Python node: implemented. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | no | Client-chosen unique key (1 to 255 printable ASCII characters, a UUID is ideal). A repeat of the same request with the same key within 24 hours returns the first response with Idempotent-Replayed: true. The same key with a different body returns 422 idempotency_key_reuse; a repeat while the first call is still running returns 409 idempotency_in_progress. |
Request body
application/json, required, schema ItemCreate
| Field | Type | Required | Description |
|---|---|---|---|
owner | string | no | Handle of an organization you can write for. Defaults to you. |
slug | string | yes | Lowercase letters, digits, dots, underscores and hyphens; starts and ends with a letter or digit. |
kind | ItemKind | yes | Kinds that can be published and sold on ReuseForge. |
title | string | yes | |
summary | string | no | |
readme | string | no | |
visibility | string: public, unlisted, private | no | Default "public". |
license | string | no | Default "UNKNOWN". |
pricing_model | string: free, fixed, pwyw | no | Default "free". |
price_cents | integer | no | Default 0. |
capabilities | array of string | no | |
tags | array of string | no | |
homepage_url | string | no | |
source | ItemSource | no | |
forked_from | ItemRef | no | Canonical item address owner/slug. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 201 Created | The created item. | application/json: Item |
| 400 | The request is malformed (bad JSON, unknown or mistyped parameter, invalid cursor). | Problem. Codes: invalid_request, invalid_json, invalid_parameter, invalid_cursor, idempotency_key_required |
| 401 | Missing, malformed, expired or revoked credentials. | Problem. Codes: unauthorized, invalid_token, token_expired |
| 403 | Authenticated, 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 |
| 409 | The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict). | Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress |
| 413 | The body or a file exceeds a limit published in get_api_index. | Problem. Codes: payload_too_large |
| 422 | The body is well-formed JSON but invalid (validation_failed with per-field errors), or a business rule rejects it (payment_invalid, webhook_url_forbidden, idempotency_key_reuse). | Problem. Codes: validation_failed, payment_invalid, rail_unsupported, idempotency_key_reuse, webhook_url_forbidden, invalid_signature, integrity_mismatch |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl -X POST 'https://reuseforge.com/api/v1/items' \
-H "Authorization: Bearer $REUSEFORGE_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"owner": "acme",
"slug": "pdf-text-layer",
"kind": "skill",
"title": "PDF text layer",
"summary": "Recovers a reading-order text layer from scanned PDFs.",
"readme": "# PDF text layer\n\nRecovers reading order from scans.",
"license": "MIT",
"pricing_model": "free",
"price_cents": 0,
"capabilities": [
"document-parsing"
],
"tags": [
"pdf",
"ocr"
],
"source": {
"provider": "github",
"url": "https://github.com/acme/pdf-text-layer",
"ref": "acme/pdf-text-layer"
}
}'Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
result = client.create_item(
owner="acme",
slug="pdf-text-layer",
kind="skill",
title="PDF text layer",
summary="Recovers a reading-order text layer from scanned PDFs.",
readme="# PDF text layer\n\nRecovers reading order from scans.",
license="MIT",
pricing_model="free",
price_cents=0,
capabilities=["document-parsing"],
tags=["pdf", "ocr"],
source={
"provider": "github",
"url": "https://github.com/acme/pdf-text-layer",
"ref": "acme/pdf-text-layer",
},
)
print(result["full_name"])JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
const result = await client.createItem({
owner: "acme",
slug: "pdf-text-layer",
kind: "skill",
title: "PDF text layer",
summary: "Recovers a reading-order text layer from scanned PDFs.",
readme: "# PDF text layer\n\nRecovers reading order from scans.",
license: "MIT",
pricing_model: "free",
price_cents: 0,
capabilities: ["document-parsing"],
tags: ["pdf", "ocr"],
source: {
provider: "github",
url: "https://github.com/acme/pdf-text-layer",
ref: "acme/pdf-text-layer",
},
});
console.log(result.full_name);CLI
rf items create acme/invoice-extractor --kind skill --title 'PDF text layer' --summary 'Recovers a reading-order text layer from scanned PDFs.' --readme '# PDF text layer
Recovers reading order from scans.' --license MIT --pricing-model free --price 0
# rf items create <item> [options]
# all options: rf items create --helpResponse 201 Created:
{
"id": "itm_pdftextlayer",
"object": "item",
"owner": {
"id": "acc_acmelabsorg2",
"type": "org",
"handle": "acme",
"display_name": "Acme Labs",
"verified": true,
"avatar_url": ""
},
"slug": "pdf-text-layer",
"full_name": "acme/pdf-text-layer",
"kind": "skill",
"title": "PDF text layer",
"summary": "Recovers a reading-order text layer from scanned PDFs.",
"readme": "# PDF text layer\n\nRecovers reading order from scans.",
"visibility": "public",
"status": "draft",
"license": "MIT",
"pricing_model": "free",
"price_cents": 0,
"currency": "USD",
"source": {
"provider": "github",
"url": "https://github.com/acme/pdf-text-layer",
"ref": "acme/pdf-text-layer"
},
"homepage_url": "",
"html_url": "https://reuseforge.com/app/acme/pdf-text-layer",
"capabilities": [
"document-parsing"
],
"tags": [
"pdf",
"ocr"
],
"latest_version": null,
"verification": null,
"stats": {
"stars": 0,
"downloads": 0,
"reviews": 0,
"sales": 0
},
"signals": {},
"rating": null,
"rating_count": 0,
"demo": false,
"forked_from": null,
"project_id": null,
"created_at": "2026-11-03T10:20:00Z",
"updated_at": "2026-11-03T10:20:00Z"
}Get an item
GET /items/{owner}/{slug} Enabled on reuseforge.com
Returns the item with its README and, when signed in, your viewer state. Supports ETag / If-None-Match. A retracted item that had been publicly listed returns 410 to everyone except its owners; an item that was never listed (draft, archived or private when it was retracted) stays 404, so a retraction reveals nothing about it.
| Property | Value |
|---|---|
| Operation ID | get_item |
| Authentication | None required. A token raises your rate limits and shows your private items. |
| Rate tier | read: 60/min per IP anonymous, 600/min per token with a token |
| Caching | Sends an ETag; repeat with If-None-Match to get 304 Not Modified |
| Python SDK | client.get_item(...) |
| JavaScript SDK | client.getItem(...) |
| CLI | rf items get |
| MCP tool | get_item |
| Deployments | reuseforge.com: enabled. Python node: implemented. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | Handle of the owning user or organization. |
slug | path | string | yes | Item slug, unique per owner. |
If-None-Match | header | string | no | ETag from an earlier response; a match returns 304 without a body. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 OK | The item. | application/json: Item |
| 304 Not Modified | Not modified. The If-None-Match ETag is still current. | no body |
| 404 | No such resource, or it is private and the caller may not know it exists. | Problem. Codes: not_found |
| 410 | The resource existed and is permanently unavailable (retracted item, expired plan). | Problem. Codes: gone, plan_expired |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl 'https://reuseforge.com/api/v1/items/acme/invoice-extractor'Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
result = client.get_item("acme/invoice-extractor")
print(result["full_name"])JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
const result = await client.getItem("acme/invoice-extractor");
console.log(result.full_name);CLI
rf items get acme/invoice-extractor
# rf items get <item> [options]
# all options: rf items get --helpResponse 200 OK:
{
"id": "itm_ragharness22",
"object": "item",
"owner": {
"id": "acc_janedoeuser2",
"type": "user",
"handle": "janedoe",
"display_name": "Jane Doe",
"verified": false,
"avatar_url": "https://avatars.githubusercontent.com/u/1000001"
},
"slug": "invoice-rag-harness",
"full_name": "janedoe/invoice-rag-harness",
"kind": "harness",
"title": "Invoice RAG harness",
"summary": "Agent harness that indexes invoices, answers spend questions with citations and exports a dashboard.",
"readme": "# Invoice RAG harness\n\nIndex a folder of invoices and ask questions.\n\n## Quick start\n\n rf install janedoe/invoice-rag-harness\n",
"visibility": "public",
"status": "active",
"license": "Commercial-Single-Project",
"pricing_model": "fixed",
"price_cents": 1200,
"currency": "USD",
"source": {
"provider": "manual",
"url": "",
"ref": ""
},
"homepage_url": "",
"html_url": "https://reuseforge.com/app/janedoe/invoice-rag-harness",
"capabilities": [
"retrieval-rag",
"llm-chat",
"data-analysis"
],
"tags": [
"rag",
"invoices",
"dashboard"
],
"latest_version": "0.9.2",
"verification": {
"state": "passed",
"version": "0.9.2",
"tests_pass_rate": 0.91,
"verified_at": "2026-10-30T16:41:05Z"
},
"stats": {
"stars": 37,
"downloads": 64,
"reviews": 3,
"sales": 11
},
"signals": {
"stars": 37,
"downloads": 64,
"tests_pass_rate": 0.91,
"days_since_update": 4
},
"rating": 4.3,
"rating_count": 3,
"demo": false,
"forked_from": null,
"project_id": null,
"viewer": {
"starred": false,
"can_edit": false,
"entitled": false
},
"created_at": "2026-09-12T08:00:00Z",
"updated_at": "2026-10-30T16:40:12Z"
}Update an item
PATCH /items/{owner}/{slug} Enabled on reuseforge.com
JSON Merge Patch style update of mutable metadata: omitted fields are unchanged, present fields replace the stored value (arrays and source members are replaced, not merged). null is not accepted; send an empty string (or an empty array for tags and capabilities) to clear a field. slug, kind and owner cannot change. If-Match is required and takes the ETag of a get_item or earlier update_item response: it holds as long as nothing you can edit changed since, even when counters (stars, downloads, reviews) moved; otherwise 412 with current_etag. A retracted item returns 409 invalid_state. Price changes never affect orders that already exist.
| Property | Value |
|---|---|
| Operation ID | update_item |
| Authentication | Bearer token holding items:write |
| Rate tier | write: not allowed anonymous, 120/min per token with a token |
| Concurrency | If-Match with the ETag from get_item, required (428 without it, 412 when stale) |
| Python SDK | client.update_item(...) |
| JavaScript SDK | client.updateItem(...) |
| CLI | rf items update |
| MCP tool | update_item |
| Deployments | reuseforge.com: enabled. Python node: not implemented (answers 501). |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | Handle of the owning user or organization. |
slug | path | string | yes | Item slug, unique per owner. |
If-Match | header | string | yes | The ETag of the representation you are changing. Mismatch returns 412, omission returns 428. |
Request body
application/merge-patch+json, required, schema ItemUpdate
| Field | Type | Required | Description |
|---|---|---|---|
title | string | no | |
summary | string | no | |
readme | string | no | |
visibility | string: public, unlisted, private | no | |
status | string: draft, active, archived | no | |
license | string | no | |
pricing_model | string: free, fixed, pwyw | no | |
price_cents | integer | no | |
capabilities | array of string | no | |
tags | array of string | no | |
homepage_url | string | no | |
source | ItemSource | no |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 OK | The updated item. | application/json: Item |
| 400 | The request is malformed (bad JSON, unknown or mistyped parameter, invalid cursor). | Problem. Codes: invalid_request, invalid_json, invalid_parameter, invalid_cursor, idempotency_key_required |
| 401 | Missing, malformed, expired or revoked credentials. | Problem. Codes: unauthorized, invalid_token, token_expired |
| 403 | Authenticated, 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 |
| 404 | No such resource, or it is private and the caller may not know it exists. | Problem. Codes: not_found |
| 409 | The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict). | Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress |
| 410 | The resource existed and is permanently unavailable (retracted item, expired plan). | Problem. Codes: gone, plan_expired |
| 412 | If-Match does not match the current ETag. current_etag carries the new one; re-read, merge, retry. | Problem. Codes: precondition_failed |
| 422 | The body is well-formed JSON but invalid (validation_failed with per-field errors), or a business rule rejects it (payment_invalid, webhook_url_forbidden, idempotency_key_reuse). | Problem. Codes: validation_failed, payment_invalid, rail_unsupported, idempotency_key_reuse, webhook_url_forbidden, invalid_signature, integrity_mismatch |
| 428 | The operation requires If-Match. | Problem. Codes: precondition_required |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl -X PATCH 'https://reuseforge.com/api/v1/items/acme/invoice-extractor' \
-H "Authorization: Bearer $REUSEFORGE_TOKEN" \
-H 'If-Match: "<etag from the GET>"' \
-H "Content-Type: application/json" \
-d '{
"homepage_url": "https://acme.example/invoice-extractor"
}'Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
result = client.update_item(
"acme/invoice-extractor",
homepage_url="https://acme.example/invoice-extractor",
if_match="auto",
)
print(result["full_name"])JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
const result = await client.updateItem("acme/invoice-extractor", { homepage_url: "https://acme.example/invoice-extractor", ifMatch: "auto" });
console.log(result.full_name);CLI
rf items update acme/invoice-extractor
# rf items update <item> [options]
# all options: rf items update --helpResponse 200 OK:
{
"id": "itm_invoiceextr2",
"object": "item",
"owner": {
"id": "acc_acmelabsorg2",
"type": "org",
"handle": "acme",
"display_name": "Acme Labs",
"verified": true,
"avatar_url": ""
},
"slug": "invoice-extractor",
"full_name": "acme/invoice-extractor",
"kind": "skill",
"title": "Invoice extractor",
"summary": "Extracts vendor, totals and line items from PDF invoices into JSON using layout-aware OCR.",
"visibility": "public",
"status": "active",
"license": "MIT",
"pricing_model": "free",
"price_cents": 0,
"currency": "USD",
"source": {
"provider": "github",
"url": "https://github.com/acme/invoice-extractor",
"ref": "acme/invoice-extractor"
},
"homepage_url": "https://acme.example/invoice-extractor",
"html_url": "https://reuseforge.com/app/acme/invoice-extractor",
"capabilities": [
"document-parsing",
"data-analysis"
],
"tags": [
"pdf",
"invoices",
"ocr"
],
"latest_version": "1.4.0",
"verification": {
"state": "passed",
"version": "1.4.0",
"tests_pass_rate": 0.97,
"verified_at": "2026-10-28T09:12:40Z"
},
"stats": {
"stars": 412,
"downloads": 9120,
"reviews": 18,
"sales": 0
},
"signals": {
"stars": 1860,
"downloads": 9120,
"tests_pass_rate": 0.97,
"forks": 143,
"open_issues": 12,
"days_since_update": 6
},
"rating": 4.6,
"rating_count": 18,
"demo": false,
"forked_from": null,
"project_id": null,
"created_at": "2026-03-02T14:05:11Z",
"updated_at": "2026-10-28T09:10:02Z"
}Retract an item
DELETE /items/{owner}/{slug} Enabled on reuseforge.com
Removes the item from search and sets status to retracted. Versions already bought stay downloadable by their buyers. Fires item.retracted. Idempotent.
| Property | Value |
|---|---|
| Operation ID | retract_item |
| Authentication | Bearer token holding items:write |
| Rate tier | write: not allowed anonymous, 120/min per token with a token |
| Python SDK | client.retract_item(...) |
| JavaScript SDK | client.retractItem(...) |
| CLI | rf items retract |
| MCP tool | retract_item |
| Deployments | reuseforge.com: enabled. Python node: implemented. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | Handle of the owning user or organization. |
slug | path | string | yes | Item slug, unique per owner. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 204 No Content | Retracted. | no body |
| 401 | Missing, malformed, expired or revoked credentials. | Problem. Codes: unauthorized, invalid_token, token_expired |
| 403 | Authenticated, 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 |
| 404 | No such resource, or it is private and the caller may not know it exists. | Problem. Codes: not_found |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl -X DELETE 'https://reuseforge.com/api/v1/items/acme/invoice-extractor' \
-H "Authorization: Bearer $REUSEFORGE_TOKEN"Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
client.retract_item("acme/invoice-extractor")JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
await client.retractItem("acme/invoice-extractor");CLI
rf items retract acme/invoice-extractor
# rf items retract <item>
# all options: rf items retract --helpResponse 204 No Content with an empty body.
Star an item
PUT /items/{owner}/{slug}/star Enabled on reuseforge.com
Idempotent. Starring twice leaves one star.
| Property | Value |
|---|---|
| Operation ID | star_item |
| Authentication | Bearer token holding items:write |
| Rate tier | write: not allowed anonymous, 120/min per token with a token |
| Python SDK | client.star_item(...) |
| JavaScript SDK | client.starItem(...) |
| CLI | rf items star |
| MCP tool | star_item |
| Deployments | reuseforge.com: enabled. Python node: not implemented (answers 501). |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | Handle of the owning user or organization. |
slug | path | string | yes | Item slug, unique per owner. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 OK | The new state. | application/json: StarState |
| 401 | Missing, malformed, expired or revoked credentials. | Problem. Codes: unauthorized, invalid_token, token_expired |
| 403 | Authenticated, 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 |
| 404 | No such resource, or it is private and the caller may not know it exists. | Problem. Codes: not_found |
| 410 | The resource existed and is permanently unavailable (retracted item, expired plan). | Problem. Codes: gone, plan_expired |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl -X PUT 'https://reuseforge.com/api/v1/items/acme/invoice-extractor/star' \
-H "Authorization: Bearer $REUSEFORGE_TOKEN"Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
result = client.star_item("acme/invoice-extractor")
print(result)JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
const result = await client.starItem("acme/invoice-extractor");
console.log(result);CLI
rf items star acme/invoice-extractor
# rf items star <item>
# all options: rf items star --helpResponse 200 OK:
{
"item": "acme/invoice-extractor",
"starred": true,
"stars_count": 413
}Remove your star
DELETE /items/{owner}/{slug}/star Enabled on reuseforge.com
Idempotent.
| Property | Value |
|---|---|
| Operation ID | unstar_item |
| Authentication | Bearer token holding items:write |
| Rate tier | write: not allowed anonymous, 120/min per token with a token |
| Python SDK | client.unstar_item(...) |
| JavaScript SDK | client.unstarItem(...) |
| CLI | rf items unstar |
| MCP tool | unstar_item |
| Deployments | reuseforge.com: enabled. Python node: not implemented (answers 501). |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | Handle of the owning user or organization. |
slug | path | string | yes | Item slug, unique per owner. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 OK | The new state. | application/json: StarState |
| 401 | Missing, malformed, expired or revoked credentials. | Problem. Codes: unauthorized, invalid_token, token_expired |
| 403 | Authenticated, 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 |
| 404 | No such resource, or it is private and the caller may not know it exists. | Problem. Codes: not_found |
| 410 | The resource existed and is permanently unavailable (retracted item, expired plan). | Problem. Codes: gone, plan_expired |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl -X DELETE 'https://reuseforge.com/api/v1/items/acme/invoice-extractor/star' \
-H "Authorization: Bearer $REUSEFORGE_TOKEN"Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
result = client.unstar_item("acme/invoice-extractor")
print(result)JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
const result = await client.unstarItem("acme/invoice-extractor");
console.log(result);CLI
rf items unstar acme/invoice-extractor
# rf items unstar <item>
# all options: rf items unstar --helpResponse 200 OK:
{
"item": "acme/invoice-extractor",
"starred": false,
"stars_count": 412
}Item statistics
GET /items/{owner}/{slug}/stats Enabled on reuseforge.com
Public totals for anyone. Owners and organization members additionally receive the daily series; revenue_cents is added for owners and organization admins when the payments ledger reports a figure.
| Property | Value |
|---|---|
| Operation ID | get_item_stats |
| Authentication | None required. A token raises your rate limits and shows your private items. |
| Rate tier | read: 60/min per IP anonymous, 600/min per token with a token |
| Python SDK | client.get_item_stats(...) |
| JavaScript SDK | client.getItemStats(...) |
| CLI | rf items stats |
| MCP tool | get_item_stats |
| Deployments | reuseforge.com: enabled. Python node: implemented. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | Handle of the owning user or organization. |
slug | path | string | yes | Item slug, unique per owner. |
days | query | integer | no | Length of the daily series for owners. Default 30. |
Responses
| Status | Meaning | Body |
|---|---|---|
| 200 OK | Statistics. | application/json: ItemStats |
| 404 | No such resource, or it is private and the caller may not know it exists. | Problem. Codes: not_found |
| 410 | The resource existed and is permanently unavailable (retracted item, expired plan). | Problem. Codes: gone, plan_expired |
| 429 | Rate limit for the operation's tier exceeded. Wait Retry-After seconds. | Problem. Codes: rate_limited |
Example
curl
curl 'https://reuseforge.com/api/v1/items/acme/invoice-extractor/stats'Python
import reuseforge
client = reuseforge.Client() # token from REUSEFORGE_TOKEN, or the file `rf login` wrote
result = client.get_item_stats("acme/invoice-extractor")
print(result)JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge({ token: process.env.REUSEFORGE_TOKEN });
const result = await client.getItemStats("acme/invoice-extractor");
console.log(result);CLI
rf items stats acme/invoice-extractor
# rf items stats <item> [options]
# all options: rf items stats --helpResponse 200 OK:
{
"item": "janedoe/invoice-rag-harness",
"totals": {
"views": 5410,
"downloads": 64,
"stars": 37,
"reviews": 3,
"sales": 11,
"revenue_cents": 13068
},
"days": [
{
"day": "2026-11-01",
"views": 188,
"downloads": 3,
"stars": 1
},
{
"day": "2026-11-02",
"views": 203,
"downloads": 2,
"stars": 0
}
]
}