On this page

API

Projects operations

Crowdfunded builds with milestones and revenue units.

Crowdfunded builds with milestones and revenue units. Paths are relative to https://reuseforge.com/api/v1.

Operations in this area
OperationMethodPath
List crowdfunded projectsGET/projects
Propose a crowdfunded projectPOST/projects
Get a projectGET/projects/{project_id}
Back a projectPOST/projects/{project_id}/backings
Withdraw a pledgeDELETE/projects/{project_id}/backings/{backing_id}
Deliver a milestone (developer)POST/projects/{project_id}/milestones/{index}/delivery
Vote on a milestone (backer)POST/projects/{project_id}/milestones/{index}/votes
Finalize a milestone votePOST/projects/{project_id}/milestones/{index}/finalize
Vote to abort a funded projectPOST/projects/{project_id}/abort-votes
Transfer revenue unitsPOST/projects/{project_id}/transfers
Attach the finished productPUT/projects/{project_id}/product
Project portfolioGET/portfolio

List crowdfunded projects

GET /projects Not enabled on reuseforge.com yet

Public listing of projects with funding progress. Newest first.

List crowdfunded projects: facts
PropertyValue
Operation IDlist_projects
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
Python SDKclient.list_projects(...)
JavaScript SDKclient.listProjects(...)
CLIrf projects list
MCP toollist_projects
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

List crowdfunded projects: parameters
NameInTypeRequiredDescription
statequeryProjectStateno
proposerquerystringnoHandle of the proposing account.
cursorquerystringnoOpaque cursor from the previous page's next_cursor.
limitqueryintegernoPage size. Default 30.

Responses

List crowdfunded projects: responses
StatusMeaningBody
200 OKA page of projects.application/json: ProjectPage
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/projects'

Python

python
import reuseforge

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

for entry in client.list_projects():  # iterating fetches further pages on demand
    print(entry["id"])

JavaScript

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

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

for await (const entry of client.listProjects()) {  // iterating fetches further pages on demand
  console.log(entry.id);
}

CLI

bash
rf projects list

# rf projects list [options]
# all options: rf projects list --help

Response 200 OK:

json
{
  "data": [
    {
      "id": "prj_reconharnes2",
      "object": "project",
      "title": "Invoice reconciliation harness",
      "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
      "deliverables": [
        "reconciliation harness",
        "evaluation set"
      ],
      "proposer": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "state": "funded",
      "goal_cents": 500000,
      "raised_cents": 500000,
      "pending_cents": 0,
      "progress": 1.0,
      "currency": "USD",
      "created_at": "2026-10-05T08:00:00Z",
      "deadline_at": "2026-11-04T08:00:00Z",
      "funded_at": "2026-10-18T13:45:00Z",
      "developers": [
        {
          "account": {
            "id": "acc_janedoeuser2",
            "type": "user",
            "handle": "janedoe",
            "display_name": "Jane Doe",
            "verified": false,
            "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
          },
          "budget_bps": 10000,
          "equity_bps": 2000
        }
      ],
      "milestones": [
        {
          "index": 0,
          "name": "Ingestion pipeline",
          "bps": 3000,
          "amount_cents": 150000,
          "state": "approved",
          "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
          "submitted_by": {
            "id": "acc_janedoeuser2",
            "type": "user",
            "handle": "janedoe",
            "display_name": "Jane Doe",
            "verified": false,
            "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
          },
          "submitted_at": "2026-10-20T09:00:00Z",
          "decided_at": "2026-10-21T15:30:00Z",
          "submissions": 1,
          "votes": {
            "approve_weight": 400000,
            "reject_weight": 0,
            "total_weight": 500000
          }
        },
        {
          "index": 1,
          "name": "Reconciliation engine",
          "bps": 4000,
          "amount_cents": 200000,
          "state": "submitted",
          "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
          "submitted_by": {
            "id": "acc_janedoeuser2",
            "type": "user",
            "handle": "janedoe",
            "display_name": "Jane Doe",
            "verified": false,
            "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
          },
          "submitted_at": "2026-11-02T12:00:00Z",
          "decided_at": null,
          "submissions": 1,
          "votes": {
            "approve_weight": 100000,
            "reject_weight": 0,
            "total_weight": 500000
          }
        },
        {
          "index": 2,
          "name": "Dashboard and docs",
          "bps": 3000,
          "amount_cents": 150000,
          "state": "pending",
          "evidence": null,
          "submitted_by": null,
          "submitted_at": null,
          "decided_at": null,
          "submissions": 0,
          "votes": {
            "approve_weight": 0,
            "reject_weight": 0,
            "total_weight": 500000
          }
        }
      ],
      "cap_table": [
        {
          "holder": {
            "id": "acc_janedoeuser2",
            "type": "user",
            "handle": "janedoe",
            "display_name": "Jane Doe",
            "verified": false,
            "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
          },
          "units": 200000000000,
          "ownership_bps": 2000
        },
        {
          "holder": {
            "id": "acc_samdevuser22",
            "type": "user",
            "handle": "samdev",
            "display_name": "Sam Okafor",
            "verified": false,
            "avatar_url": ""
          },
          "units": 480000000000,
          "ownership_bps": 4800
        },
        {
          "holder": {
            "id": "acc_acmelabsorg2",
            "type": "org",
            "handle": "acme",
            "display_name": "Acme Labs",
            "verified": true,
            "avatar_url": ""
          },
          "units": 320000000000,
          "ownership_bps": 3200
        }
      ],
      "total_units": 1000000000000,
      "dividends_cents": 0,
      "product": null,
      "share_token": null
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Propose a crowdfunded project

POST /projects Not enabled on reuseforge.com yet

Opens a project: backers fund a goal, developers are hired for the deliverables, backers receive revenue units in proportion to their pledge and developers a pre-agreed share capped at 5000 bps. Developer budget_bps must total 10000 and milestone bps must total 10000. Milestones are approved by pledge-weighted vote and paid from escrow. Revenue units may be regulated securities where you live; payments run on the simulated or test rails until the operator enables real ones.

Propose a crowdfunded project: facts
PropertyValue
Operation IDcreate_project
AuthenticationBearer token holding projects:write
Rate tierwrite: not allowed anonymous, 120/min per token with a token
IdempotencyIdempotency-Key header, optional. The SDKs and the CLI send one for you.
Python SDKclient.create_project(...)
JavaScript SDKclient.createProject(...)
CLIrf projects create
MCP toolcreate_project
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Propose a crowdfunded project: parameters
NameInTypeRequiredDescription
Idempotency-KeyheaderstringnoClient-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 ProjectCreate

Propose a crowdfunded project: request fields
FieldTypeRequiredDescription
titlestringyes
specstringno
deliverablesarray of stringyes
goal_centsintegeryes
deadline_daysnumbernoDefault 30.
developersarray of objectyes
developers[].accountstringyesHandle or account id of the developer.
developers[].budget_bpsintegeryes
developers[].equity_bpsintegeryes
milestonesarray of objectyes
milestones[].namestringyes
milestones[].bpsintegeryes

Responses

Propose a crowdfunded project: responses
StatusMeaningBody
201 CreatedThe open project.application/json: Project
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
422The 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
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "goal_cents": 500000,
  "deadline_days": 30,
  "developers": [
    {
      "account": "janedoe",
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "name": "Ingestion pipeline",
      "bps": 3000
    },
    {
      "name": "Reconciliation engine",
      "bps": 4000
    },
    {
      "name": "Dashboard and docs",
      "bps": 3000
    }
  ]
}'

Python

python
import reuseforge

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

result = client.create_project(
    title="Invoice reconciliation harness",
    spec="A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
    deliverables=["reconciliation harness", "evaluation set"],
    goal_cents=500000,
    deadline_days=30,
    developers=[{"account": "janedoe", "budget_bps": 10000, "equity_bps": 2000}],
    milestones=[
            {"name": "Ingestion pipeline", "bps": 3000},
            {"name": "Reconciliation engine", "bps": 4000},
            {"name": "Dashboard and docs", "bps": 3000},
        ],
)
print(result["id"])

JavaScript

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

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

const result = await client.createProject({
  title: "Invoice reconciliation harness",
  spec: "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  deliverables: ["reconciliation harness", "evaluation set"],
  goal_cents: 500000,
  deadline_days: 30,
  developers: [{ account: "janedoe", budget_bps: 10000, equity_bps: 2000 }],
  milestones: [
    { name: "Ingestion pipeline", bps: 3000 },
    { name: "Reconciliation engine", bps: 4000 },
    { name: "Dashboard and docs", bps: 3000 },
  ],
});
console.log(result.id);

CLI

bash
rf projects create --title 'Invoice reconciliation harness' --spec 'A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.' --goal 5000 --deadline-days 30

# rf projects create [options]
# all options: rf projects create --help

Response 201 Created:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "open",
  "goal_cents": 500000,
  "raised_cents": 0,
  "pending_cents": 0,
  "progress": 0.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": null,
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 0
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 0
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 0
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Get a project

GET /projects/{project_id} Not enabled on reuseforge.com yet

Funding state, milestones with vote tallies, the cap table and dividends.

Get a project: facts
PropertyValue
Operation IDget_project
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
Python SDKclient.get_project(...)
JavaScript SDKclient.getProject(...)
CLIrf projects get
MCP toolget_project
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Get a project: parameters
NameInTypeRequiredDescription
project_idpathstringyes

Responses

Get a project: responses
StatusMeaningBody
200 OKThe project.application/json: Project
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/projects/prj_reconharnes2'

Python

python
import reuseforge

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

result = client.get_project("prj_reconharnes2")
print(result["id"])

JavaScript

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

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

const result = await client.getProject("prj_reconharnes2");
console.log(result.id);

CLI

bash
rf projects get prj_reconharnes2

# rf projects get <project_id>
# all options: rf projects get --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Back a project

POST /projects/{project_id}/backings Not enabled on reuseforge.com yet

Pledges money to an open project. Pledges cannot exceed the remaining goal; the pledge that reaches the goal flips the project to funded. Spends money, so the token needs orders:pay and the amount counts against its spend limit. Pledges can be withdrawn with withdraw_backing until the project is funded. Idempotency-Key is required.

Back a project: facts
PropertyValue
Operation IDback_project
AuthenticationBearer token holding projects:write and orders:pay (all are required)
Rate tierpayments: not allowed anonymous, 30/min per token with a token
IdempotencyIdempotency-Key header, required. Money moves here, so it is not optional.
Python SDKclient.back_project(...)
JavaScript SDKclient.backProject(...)
CLIrf projects back
MCP toolback_project
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Back a project: parameters
NameInTypeRequiredDescription
project_idpathstringyes
Idempotency-KeyheaderstringyesRequired here because the call moves or commits money. Same semantics as the optional header; omitting it returns 400 idempotency_key_required.

Request body

application/json, required, schema BackProject

Back a project: request fields
FieldTypeRequiredDescription
amount_centsintegeryes
railPaymentRailnoOpen set. Known: simulated, base-usdc, base-usdt, btc. Python nodes also use usdc-base and usdt-ethereum.
tx_refstringno
walletstringno

Another body: onchain

json
{
  "amount_cents": 300000,
  "rail": "base-usdc",
  "tx_ref": "0x709b55bd3da0f5a838125bd0ee20c5bfdd7caba173912d4281cae816b79a201b",
  "wallet": "0x1D6c2b7A0E5a3C47bC8D90e5F0A2c1b3d4E5f6A7"
}

Responses

Back a project: responses
StatusMeaningBody
201 CreatedThe backing.application/json: Backing
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
422The 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
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/backings' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "amount_cents": 300000,
  "rail": "simulated"
}'

Python

python
import reuseforge

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

result = client.back_project(
    "prj_reconharnes2",
    amount_cents=300000,
    rail="simulated",
)
print(result["id"])

JavaScript

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

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

const result = await client.backProject("prj_reconharnes2", { amount_cents: 300000, rail: "simulated" });
console.log(result.id);

CLI

bash
rf projects back prj_reconharnes2 --amount 3000 --rail simulated

# rf projects back <project_id> [options]
# all options: rf projects back --help

Response 201 Created:

json
{
  "id": "bck_samreconpldg",
  "object": "backing",
  "project_id": "prj_reconharnes2",
  "backer": {
    "id": "acc_samdevuser22",
    "type": "user",
    "handle": "samdev",
    "display_name": "Sam Okafor",
    "verified": false,
    "avatar_url": ""
  },
  "amount_cents": 300000,
  "currency": "USD",
  "state": "confirmed",
  "units": 480000000000,
  "payment": {
    "rail": "simulated",
    "network": null,
    "asset": "USD",
    "status": "confirmed",
    "amount_cents": 300000,
    "amount_atomic": "300000",
    "address": "escrow:rb-hosted",
    "memo": "bck_samreconpldg",
    "uri": null,
    "tx_ref": "sim_tx_5d1f08a9c3e2",
    "confirmations": 1,
    "required_confirmations": 1,
    "expires_at": null,
    "refund_address": null,
    "simulated": true
  },
  "created_at": "2026-10-12T17:20:00Z"
}

Withdraw a pledge

DELETE /projects/{project_id}/backings/{backing_id} Not enabled on reuseforge.com yet

Returns a pledge to the backer and burns its units. Only while the project is open. Idempotent.

Withdraw a pledge: facts
PropertyValue
Operation IDwithdraw_backing
AuthenticationBearer token holding projects:write
Rate tierpayments: not allowed anonymous, 30/min per token with a token
Python SDKclient.withdraw_backing(...)
JavaScript SDKclient.withdrawBacking(...)
CLIrf projects withdraw
MCP toolwithdraw_backing
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: not implemented (answers 501).

Parameters

Withdraw a pledge: parameters
NameInTypeRequiredDescription
project_idpathstringyes
backing_idpathstringyes

Responses

Withdraw a pledge: responses
StatusMeaningBody
204 No ContentWithdrawn.no body
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X DELETE 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/backings/bck_h4m6t1y9d2z8' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN"

Python

python
import reuseforge

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

client.withdraw_backing("prj_reconharnes2", "bck_h4m6t1y9d2z8")

JavaScript

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

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

await client.withdrawBacking("prj_reconharnes2", "bck_h4m6t1y9d2z8");

CLI

bash
rf projects withdraw prj_reconharnes2 bck_h4m6t1y9d2z8

# rf projects withdraw <project_id> <backing_id>
# all options: rf projects withdraw --help

Response 204 No Content with an empty body.

Deliver a milestone (developer)

POST /projects/{project_id}/milestones/{index}/delivery Not enabled on reuseforge.com yet

A developer submits evidence (a link, commit or release) for a milestone. A new submission restarts the vote. A rejected milestone may be resubmitted at most three times.

Deliver a milestone (developer): facts
PropertyValue
Operation IDdeliver_milestone
AuthenticationBearer token holding projects:write
Rate tierwrite: not allowed anonymous, 120/min per token with a token
IdempotencyIdempotency-Key header, optional. The SDKs and the CLI send one for you.
Python SDKclient.deliver_milestone(...)
JavaScript SDKclient.deliverMilestone(...)
CLIrf projects deliver
MCP tooldeliver_milestone
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Deliver a milestone (developer): parameters
NameInTypeRequiredDescription
project_idpathstringyes
indexpathintegeryesZero-based milestone index.
Idempotency-KeyheaderstringnoClient-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 DeliverMilestone

Deliver a milestone (developer): request fields
FieldTypeRequiredDescription
evidencestringyes

Responses

Deliver a milestone (developer): responses
StatusMeaningBody
200 OKThe project with the submitted milestone.application/json: Project
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/milestones/0/delivery' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "evidence": "https://github.com/janedoe/invoice-recon/pull/9"
}'

Python

python
import reuseforge

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

result = client.deliver_milestone(
    "prj_reconharnes2",
    0,
    evidence="https://github.com/janedoe/invoice-recon/pull/9",
)
print(result["id"])

JavaScript

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

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

const result = await client.deliverMilestone("prj_reconharnes2", 0, { evidence: "https://github.com/janedoe/invoice-recon/pull/9" });
console.log(result.id);

CLI

bash
rf projects deliver prj_reconharnes2 0 --evidence https://github.com/janedoe/invoice-recon/pull/9

# rf projects deliver <project_id> <index> [options]
# all options: rf projects deliver --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Vote on a milestone (backer)

POST /projects/{project_id}/milestones/{index}/votes Not enabled on reuseforge.com yet

Backers approve or reject a submitted milestone, weighted by pledge amount. More than half of the goal in approving weight approves at once. A backer can change their vote until the milestone is decided.

Vote on a milestone (backer): facts
PropertyValue
Operation IDvote_milestone
AuthenticationBearer token holding projects:write
Rate tierwrite: not allowed anonymous, 120/min per token with a token
IdempotencyIdempotency-Key header, optional. The SDKs and the CLI send one for you.
Python SDKclient.vote_milestone(...)
JavaScript SDKclient.voteMilestone(...)
CLIrf projects vote
MCP toolvote_milestone
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Vote on a milestone (backer): parameters
NameInTypeRequiredDescription
project_idpathstringyes
indexpathintegeryesZero-based milestone index.
Idempotency-KeyheaderstringnoClient-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 VoteMilestone

Vote on a milestone (backer): request fields
FieldTypeRequiredDescription
approvebooleanyes

Responses

Vote on a milestone (backer): responses
StatusMeaningBody
200 OKThe project with updated tallies.application/json: Project
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/milestones/0/votes' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "approve": true
}'

Python

python
import reuseforge

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

result = client.vote_milestone("prj_reconharnes2", 0, approve=True)
print(result["id"])

JavaScript

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

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

const result = await client.voteMilestone("prj_reconharnes2", 0, { approve: true });
console.log(result.id);

CLI

bash
rf projects vote prj_reconharnes2 0 --approve

# rf projects vote <project_id> <index> [options]
# all options: rf projects vote --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Finalize a milestone vote

POST /projects/{project_id}/milestones/{index}/finalize Not enabled on reuseforge.com yet

Anyone may call this after the vote window has elapsed to apply the outcome (more approval than rejection approves; a tie with no votes goes to the arbiter). A no-op before the window ends or after a decision.

Finalize a milestone vote: facts
PropertyValue
Operation IDfinalize_milestone
AuthenticationBearer token holding projects:write
Rate tierwrite: not allowed anonymous, 120/min per token with a token
IdempotencyIdempotency-Key header, optional. The SDKs and the CLI send one for you.
Python SDKclient.finalize_milestone(...)
JavaScript SDKclient.finalizeMilestone(...)
CLIrf projects finalize
MCP toolfinalize_milestone
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Finalize a milestone vote: parameters
NameInTypeRequiredDescription
project_idpathstringyes
indexpathintegeryesZero-based milestone index.
Idempotency-KeyheaderstringnoClient-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.

Responses

Finalize a milestone vote: responses
StatusMeaningBody
200 OKThe project after finalization.application/json: Project
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/milestones/0/finalize' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

Python

python
import reuseforge

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

result = client.finalize_milestone("prj_reconharnes2", 0)
print(result["id"])

JavaScript

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

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

const result = await client.finalizeMilestone("prj_reconharnes2", 0);
console.log(result.id);

CLI

bash
rf projects finalize prj_reconharnes2 0

# rf projects finalize <project_id> <index>
# all options: rf projects finalize --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Vote to abort a funded project

POST /projects/{project_id}/abort-votes Not enabled on reuseforge.com yet

Backers holding more than half of the pledges can abort a stalled project; unreleased funds are then refunded pro rata. Set abort: false to withdraw your vote.

Vote to abort a funded project: facts
PropertyValue
Operation IDvote_abort
AuthenticationBearer token holding projects:write
Rate tierwrite: not allowed anonymous, 120/min per token with a token
IdempotencyIdempotency-Key header, optional. The SDKs and the CLI send one for you.
Python SDKclient.vote_abort(...)
JavaScript SDKclient.voteAbort(...)
CLIrf projects abort
MCP toolvote_abort
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: not implemented (answers 501).

Parameters

Vote to abort a funded project: parameters
NameInTypeRequiredDescription
project_idpathstringyes
Idempotency-KeyheaderstringnoClient-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 VoteAbort

Vote to abort a funded project: request fields
FieldTypeRequiredDescription
abortbooleanyes

Responses

Vote to abort a funded project: responses
StatusMeaningBody
200 OKThe project.application/json: Project
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/abort-votes' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "abort": true
}'

Python

python
import reuseforge

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

result = client.vote_abort("prj_reconharnes2", abort=True)
print(result["id"])

JavaScript

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

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

const result = await client.voteAbort("prj_reconharnes2", { abort: true });
console.log(result.id);

CLI

bash
rf projects abort prj_reconharnes2

# rf projects abort <project_id> [options]
# all options: rf projects abort --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Transfer revenue units

POST /projects/{project_id}/transfers Not enabled on reuseforge.com yet

Moves units to another account. Allowed once the project is funded. Dividends already accrued stay with the sender. Idempotency-Key is required.

Transfer revenue units: facts
PropertyValue
Operation IDtransfer_units
AuthenticationBearer token holding projects:write
Rate tierpayments: not allowed anonymous, 30/min per token with a token
IdempotencyIdempotency-Key header, required. Money moves here, so it is not optional.
Python SDKclient.transfer_units(...)
JavaScript SDKclient.transferUnits(...)
CLIrf projects transfer
MCP tooltransfer_units
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Transfer revenue units: parameters
NameInTypeRequiredDescription
project_idpathstringyes
Idempotency-KeyheaderstringyesRequired here because the call moves or commits money. Same semantics as the optional header; omitting it returns 400 idempotency_key_required.

Request body

application/json, required, schema TransferUnits

Transfer revenue units: request fields
FieldTypeRequiredDescription
tostringyesHandle or account id of the recipient.
unitsintegeryes

Responses

Transfer revenue units: responses
StatusMeaningBody
200 OKThe project with the new cap table.application/json: Project
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
422The 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
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X POST 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/transfers' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "acme",
  "units": 10000000000
}'

Python

python
import reuseforge

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

result = client.transfer_units("prj_reconharnes2", to="acme", units=10000000000)
print(result["id"])

JavaScript

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

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

const result = await client.transferUnits("prj_reconharnes2", { to: "acme", units: 10000000000 });
console.log(result.id);

CLI

bash
rf projects transfer prj_reconharnes2 --to acme --units 10000000000

# rf projects transfer <project_id> [options]
# all options: rf projects transfer --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Attach the finished product

PUT /projects/{project_id}/product Not enabled on reuseforge.com yet

The proposer links the completed project to the item it produced. From then on the item's sales are split across unit holders (after the platform fee). Items attached to a project accept stablecoin rails only.

Attach the finished product: facts
PropertyValue
Operation IDattach_product
AuthenticationBearer token holding projects:write
Rate tierwrite: not allowed anonymous, 120/min per token with a token
Python SDKclient.attach_product(...)
JavaScript SDKclient.attachProduct(...)
CLIrf projects attach
MCP toolattach_product
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Attach the finished product: parameters
NameInTypeRequiredDescription
project_idpathstringyes

Request body

application/json, required, schema AttachProduct

Attach the finished product: request fields
FieldTypeRequiredDescription
itemItemRefyesCanonical item address owner/slug.

Responses

Attach the finished product: responses
StatusMeaningBody
200 OKThe project with its product.application/json: Project
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
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
409The request conflicts with current state (duplicate resource, wrong lifecycle state, idempotency conflict).Problem. Codes: conflict, already_exists, invalid_state, idempotency_in_progress
429Rate limit for the operation's tier exceeded. Wait Retry-After seconds.Problem. Codes: rate_limited

Example

curl

bash
curl -X PUT 'https://reuseforge.com/api/v1/projects/prj_reconharnes2/product' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "item": "janedoe/invoice-rag-harness"
}'

Python

python
import reuseforge

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

result = client.attach_product(
    "prj_reconharnes2",
    item="janedoe/invoice-rag-harness",
)
print(result["id"])

JavaScript

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

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

const result = await client.attachProduct("prj_reconharnes2", { item: "janedoe/invoice-rag-harness" });
console.log(result.id);

CLI

bash
rf projects attach prj_reconharnes2 --item janedoe/invoice-rag-harness

# rf projects attach <project_id> [options]
# all options: rf projects attach --help

Response 200 OK:

json
{
  "id": "prj_reconharnes2",
  "object": "project",
  "title": "Invoice reconciliation harness",
  "spec": "A harness that matches supplier invoices to purchase orders and flags mismatches, shipped as a reusable skill.",
  "deliverables": [
    "reconciliation harness",
    "evaluation set"
  ],
  "proposer": {
    "id": "acc_janedoeuser2",
    "type": "user",
    "handle": "janedoe",
    "display_name": "Jane Doe",
    "verified": false,
    "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
  },
  "state": "funded",
  "goal_cents": 500000,
  "raised_cents": 500000,
  "pending_cents": 0,
  "progress": 1.0,
  "currency": "USD",
  "created_at": "2026-10-05T08:00:00Z",
  "deadline_at": "2026-11-04T08:00:00Z",
  "funded_at": "2026-10-18T13:45:00Z",
  "developers": [
    {
      "account": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "budget_bps": 10000,
      "equity_bps": 2000
    }
  ],
  "milestones": [
    {
      "index": 0,
      "name": "Ingestion pipeline",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "approved",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/4",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-10-20T09:00:00Z",
      "decided_at": "2026-10-21T15:30:00Z",
      "submissions": 1,
      "votes": {
        "approve_weight": 400000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 1,
      "name": "Reconciliation engine",
      "bps": 4000,
      "amount_cents": 200000,
      "state": "submitted",
      "evidence": "https://github.com/janedoe/invoice-recon/pull/9",
      "submitted_by": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "submitted_at": "2026-11-02T12:00:00Z",
      "decided_at": null,
      "submissions": 1,
      "votes": {
        "approve_weight": 100000,
        "reject_weight": 0,
        "total_weight": 500000
      }
    },
    {
      "index": 2,
      "name": "Dashboard and docs",
      "bps": 3000,
      "amount_cents": 150000,
      "state": "pending",
      "evidence": null,
      "submitted_by": null,
      "submitted_at": null,
      "decided_at": null,
      "submissions": 0,
      "votes": {
        "approve_weight": 0,
        "reject_weight": 0,
        "total_weight": 500000
      }
    }
  ],
  "cap_table": [
    {
      "holder": {
        "id": "acc_janedoeuser2",
        "type": "user",
        "handle": "janedoe",
        "display_name": "Jane Doe",
        "verified": false,
        "avatar_url": "https://avatars.githubusercontent.com/u/1000001"
      },
      "units": 200000000000,
      "ownership_bps": 2000
    },
    {
      "holder": {
        "id": "acc_samdevuser22",
        "type": "user",
        "handle": "samdev",
        "display_name": "Sam Okafor",
        "verified": false,
        "avatar_url": ""
      },
      "units": 480000000000,
      "ownership_bps": 4800
    },
    {
      "holder": {
        "id": "acc_acmelabsorg2",
        "type": "org",
        "handle": "acme",
        "display_name": "Acme Labs",
        "verified": true,
        "avatar_url": ""
      },
      "units": 320000000000,
      "ownership_bps": 3200
    }
  ],
  "total_units": 1000000000000,
  "dividends_cents": 0,
  "product": null,
  "share_token": null
}

Project portfolio

GET /portfolio Not enabled on reuseforge.com yet

Stakes, dividends and net result of an account across projects. Positions are public ledger data; holder defaults to you.

Project portfolio: facts
PropertyValue
Operation IDget_portfolio
AuthenticationBearer token holding projects:read
Rate tierread: 60/min per IP anonymous, 600/min per token with a token
Python SDKclient.get_portfolio(...)
JavaScript SDKclient.getPortfolio(...)
CLIrf portfolio
MCP toolget_portfolio
Deploymentsreuseforge.com: not enabled yet (answers 501 not_implemented). Python node: implemented.

Parameters

Project portfolio: parameters
NameInTypeRequiredDescription
holderquerystringnoHandle of the account. Defaults to the caller.

Responses

Project portfolio: responses
StatusMeaningBody
200 OKThe portfolio.application/json: Portfolio
401Missing, malformed, expired or revoked credentials.Problem. Codes: unauthorized, invalid_token, token_expired
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
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/portfolio' \
  -H "Authorization: Bearer $REUSEFORGE_TOKEN"

Python

python
import reuseforge

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

result = client.get_portfolio()
print(result)

JavaScript

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

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

const result = await client.getPortfolio();
console.log(result);

CLI

bash
rf portfolio

# rf portfolio [options]
# all options: rf portfolio --help

Response 200 OK:

json
{
  "holder": {
    "id": "acc_samdevuser22",
    "type": "user",
    "handle": "samdev",
    "display_name": "Sam Okafor",
    "verified": false,
    "avatar_url": ""
  },
  "currency": "USD",
  "invested_cents": 300000,
  "dividends_cents": 0,
  "net_cents": -300000,
  "positions": [
    {
      "project_id": "prj_reconharnes2",
      "title": "Invoice reconciliation harness",
      "state": "funded",
      "invested_cents": 300000,
      "units": 480000000000,
      "ownership_bps": 4800,
      "dividends_cents": 0,
      "net_cents": -300000
    }
  ]
}