Contents

Ledger and usage

Every read, change and refusal, and what this month has used.

The FolioLedgerPage object

Attributes

  • head_keys required Type: object[]
  • entries required Type: object[]
  • next_before required Type: integer null

FolioLedgerPage on its own page

Read the ledger

GET /folio/ledger

Needs folio:audit:read: Read the folio ledger

The hash-chained event ledger, newest first. It holds who, what, where and why, never document content. Reading it is itself ledgered (ledger.read). head_keys lists the public key of every stamp that signed one of the organisation's ledger heads (more than one after a move to another region). They come from the same database as the heads, so do not trust them as served: check each against the published key of the stamp it names (GET /folio/head-key on that region's host) before giving it to the offline verifier.

Parameters

  • actor queryoptional Type: string
  • action queryoptional Type: string

    An action prefix, such as record. or search.run.

  • target queryoptional Type: string

    A record id, or a folder and everything under it.

  • from queryoptional Type: integer

    Unix milliseconds, inclusive.

  • to queryoptional Type: integer

    Unix milliseconds, exclusive.

  • before queryoptional Type: integer

    The previous page's next_before.

  • limit queryoptional Type: integer

Returns

  • 200 Type: FolioLedgerPage
    A page of ledger entries
  • 400 Type: Problem
    invalid_request, invalid_version, idempotency_key_required or invalid_signature
  • 401 Type: Problem
    unauthorized
  • 403 Type: Problem
    permission_denied, org_suspended, or address_not_allowed (your organisation only accepts requests from the addresses it has listed)
  • 404 Type: Problem
    not_found
  • 421 Type: Problem
    wrong_region
  • 429 Type: Problem
    rate_limited or quota_exceeded
  • default Type: Problem
    internal
GET /folio/ledger · curl
curl "https://api.unforged.sh/folio/ledger" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14"
GET /folio/ledger · Python
import requests

r = requests.get(
    "https://api.unforged.sh/folio/ledger",
    headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json())
GET /folio/ledger · Node.js
const res = await fetch('https://api.unforged.sh/folio/ledger', {
  method: 'GET',
  headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json());

This month's usage

GET /folio/usage

Needs org:read: See org, members, usage

This month's usage by item, the storage held per profile, the download allowance and a forecast. Amounts are null (a placeholder) until prices are set.

Returns

  • 200
    This month's usage
  • 401 Type: Problem
    unauthorized
  • 403 Type: Problem
    permission_denied, org_suspended, or address_not_allowed (your organisation only accepts requests from the addresses it has listed)
  • 404 Type: Problem
    not_found
  • 421 Type: Problem
    wrong_region
  • 429 Type: Problem
    rate_limited or quota_exceeded
  • default Type: Problem
    internal
GET /folio/usage · curl
curl "https://api.unforged.sh/folio/usage" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14"
GET /folio/usage · Python
import requests

r = requests.get(
    "https://api.unforged.sh/folio/usage",
    headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json())
GET /folio/usage · Node.js
const res = await fetch('https://api.unforged.sh/folio/usage', {
  method: 'GET',
  headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json());

This month's usage as CSV

GET /folio/usage.csv

Needs org:read: See org, members, usage

The same month as CSV; it reconciles with the usage lines.

Returns

  • 200
    This month's usage as CSV
  • 401 Type: Problem
    unauthorized
  • 403 Type: Problem
    permission_denied, org_suspended, or address_not_allowed (your organisation only accepts requests from the addresses it has listed)
  • 404 Type: Problem
    not_found
  • 421 Type: Problem
    wrong_region
  • 429 Type: Problem
    rate_limited or quota_exceeded
  • default Type: Problem
    internal
GET /folio/usage.csv · curl
curl "https://api.unforged.sh/folio/usage.csv" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14"
GET /folio/usage.csv · Python
import requests

r = requests.get(
    "https://api.unforged.sh/folio/usage.csv",
    headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json())
GET /folio/usage.csv · Node.js
const res = await fetch('https://api.unforged.sh/folio/usage.csv', {
  method: 'GET',
  headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json());

This stamp's published head key

GET /folio/head-key

No API key needed

The public key this region's stamp signs ledger heads with, and its id. No key needed. A ledger names the keys that signed its heads (head_keys in GET /folio/ledger); check each against the published key of the stamp it names (this route on that region's host) before you trust it, then give them to the offline verifier. 404 where this stamp signs no heads. Limited per client address (429 rate_limited, with Retry-After).

Returns

  • 200
    The key
  • 404 Type: Problem
    not_found
  • 429 Type: Problem
    rate_limited or quota_exceeded
  • default Type: Problem
    internal
GET /folio/head-key · curl
curl "https://api.unforged.sh/folio/head-key" \
  -H "Unforged-Version: 2026-10-14"
GET /folio/head-key · Python
import requests

r = requests.get(
    "https://api.unforged.sh/folio/head-key",
    headers={"Unforged-Version": "2026-10-14"},
)
print(r.json())
GET /folio/head-key · Node.js
const res = await fetch('https://api.unforged.sh/folio/head-key', {
  method: 'GET',
  headers: { 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json());