Developer docs

Documented against main @ bbedf98 (0.8.9-dev, 4 November 2026) · latest release v0.8.8

Radicle

rad: URLs

Any page can fetch public repository data as JSON from the user's own Radicle node. No prompt, no server, no API key.

Source on GitHub
On this page

Freedom resolves the rad: scheme in-process. A page, including one served from bzz://, can read a public Radicle repository with a plain fetch(). This is the read side of Radicle in Freedom; writes such as seeding and issues go through window.radicle.

const rid = 'z3QXuMvMmSeEX3ZgoUidZC1v5MkKE';   // freedom-browser's Radicle mirror
const repo = await (await fetch(`rad:${rid}`)).json();
const head = repo.payloads['xyz.radicle.project'].meta.head;

const readme = await (await fetch(`rad:${rid}/readme/${head}`)).json();
const openIssues = await (await fetch(`rad:${rid}/issues?status=open`)).json();

URL forms#

Both forms work and are equivalent:

rad:<rid>/<route>
rad://<rid>/<route>

<rid> is the bare repository id, z followed by 20 to 60 base58 characters (no rad: prefix inside the URL). The scheme is registered as non-standard, so the browser does not lowercase it and the case-sensitive id reaches Freedom intact.

Rules#

  • Read only: GET and HEAD. Any other method is 405. HEAD returns the same status and headers without a body.
  • Public repositories only: a repository whose visibility is not public is 403 (repository is not public).
  • The node must have the repository. rad: reads from the user's local storage. To read a repository the node does not have yet, ask the user to seed it with radicle_seed and wait for state: 'fetched'.
  • Full commit SHAs: routes that take a revision need the full 40-character lowercase hex SHA; branch names and short SHAs are rejected with 400. Get the default branch head from the repository metadata.
  • CORS: responses carry Access-Control-Allow-Origin: *, so cross-origin pages can read them.
  • No consent: public repository data is world-readable on the network, so no prompt is shown and no grant is needed.
  • When Radicle is disabled for the profile, every request is 403.

Routes#

The routes mirror the per-repository part of radicle-httpd's API (/api/v1/repos/<rid>/…). Node-level endpoints (repository listing, node info, sessions) are deliberately not reachable.

Route Returns
rad:<rid> Repository metadata (shape below)
rad:<rid>/tree/<sha> The root tree at a commit
rad:<rid>/tree/<sha>/<path> A directory at a commit
rad:<rid>/blob/<sha>/<path> A file at a commit
rad:<rid>/readme/<sha> The README at a commit (404 no readme if there is none)
rad:<rid>/commits/<sha> One commit
rad:<rid>/commits?parent=<sha>&page=&perPage= Commit history from parent
rad:<rid>/stats/tree/<sha> Repository statistics at a commit
rad:<rid>/remotes The repository's remotes
rad:<rid>/issues?status=&page=&perPage= Issues
rad:<rid>/issues/<id> One issue
rad:<rid>/patches?status=&page=&perPage= Patches
rad:<rid>/patches/<id> One patch

Path segments may be URL-encoded. Empty, . and .. segments, encoded slashes and control characters are rejected (400), so a request cannot leave the repository's scope.

Repository metadata#

{
  rid: 'rad:z…',
  payloads: {
    'xyz.radicle.project': {
      data: { name, description, defaultBranch },
      meta: { head, issues: { open }, patches: { open } }
    }
  },
  delegates: [ … ],
  threshold: number,
  visibility: { type: 'public' },
  seeding: number          // number of seeders known to the node
}

meta.head is the default branch's commit SHA; use it as <sha> for the tree, blob, readme and commit routes.

Pagination and filters#

Parameter Routes Rule
page commits, issues, patches 0-based, default 0
perPage commits, issues, patches 1 to 100, default 30
parent commits Required for the history route; a full SHA
status issues, patches Keeps items whose state.status equals the value, for example open

Out-of-range values are clamped rather than rejected.

Errors#

Status Body When
400 { code, message: 'invalid rad reference' } Malformed id or unsafe path
400 { error } A route is missing its revision or path, or the SHA is not 40 hex characters
403 { code, message } Radicle is disabled for this profile
403 { error: 'repository is not public' } The repository is private
404 { error } Unknown route (unsupported endpoint: …), or the repository, object or README was not found
405 { code, message: 'method not allowed' } Not GET or HEAD
500 { error } Any other node error

Errors raised before the request reaches the repository (the first 400, the profile 403 and 405) use { code, message }; errors from the repository routes use { error }. Check response.ok before parsing.