Folders
Folders in the shape your team already works in.
The FolioFolder object
Attributes
pathrequired Type:stringmatterrequired Type:stringnullsubjectrequired Type:stringnullprotectedrequired Type:booleancreated_at_msrequired Type:integer
Protect a folder
POST /folio/folders/protect
Needs folio:settings:manage: Retention classes, reason settings, protected folders, webhooks
Views of records in the folder and every folder below it need a reason even when the organisation's view-reason setting is off. A change, so a reason is required; ledgered.
Parameters
Idempotency-Keyheaderrequired Type:string1–255 printable ASCII characters, kept 24 hours.
Request body
folderrequired Type:stringcoderequired Type:stringtextoptional Type:stringnull
Returns
200Type:FolioFolderProtectedProtected400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found409Type:Problemconflict,idempotency_conflict,idempotency_in_progressoridempotency_not_replayable413Type:Problemtoo_large421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl -X POST "https://api.unforged.sh/folio/folders/protect" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Content-Type: application/json" \
-d '{}' import requests
r = requests.post(
"https://api.unforged.sh/folio/folders/protect",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
json={},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/folio/folders/protect', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
body: JSON.stringify({}),
});
console.log(await res.json()); Ask to remove a folder's protection
POST /folio/folders/unprotect
Needs folio:settings:manage: Retention classes, reason settings, protected folders, webhooks
Nothing changes until a different person approves (POST /folio/approvals/{id}/approve, which then also needs folio:settings:manage). 409 when the folder is not protected, or a folder above it is (a sub-folder cannot opt out of its parent's protection).
Parameters
Idempotency-Keyheaderrequired Type:string1–255 printable ASCII characters, kept 24 hours.
Request body
folderrequired Type:stringcoderequired Type:stringtextoptional Type:stringnull
Returns
201Type:FolioApprovalThe approval request400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found409Type:Problemconflict,idempotency_conflict,idempotency_in_progressoridempotency_not_replayable413Type:Problemtoo_large421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl -X POST "https://api.unforged.sh/folio/folders/unprotect" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Content-Type: application/json" \
-d '{}' import requests
r = requests.post(
"https://api.unforged.sh/folio/folders/unprotect",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
json={},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/folio/folders/unprotect', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
body: JSON.stringify({}),
});
console.log(await res.json()); Rename a folder
POST /folio/folders/rename
Needs folio:records:write: File records, create folders, extend retention
Renames the last segment of path. Everything in the folder and below it keeps its place, and its path changes with it. A change, so a reason with details is required; every document gets its own ledger entry. 409 with a sentence when the folder holds a hold, an open reason, a regulator grant, a waiting approval, queued or open work, a document still being filed, more than 2,000 documents, or when the new name already exists. A protected folder returns 202 with an approval (rename_folder) that a different person decides, which then also needs folio:settings:manage.
Parameters
Idempotency-Keyheaderrequired Type:string1–255 printable ASCII characters, kept 24 hours.
Request body
pathrequired Type:stringThe folder to rename.
namerequired Type:stringIts new last segment
coderequired Type:stringThe reason code.
textoptional Type:stringnullThe reason's details (at least 10 characters).
Returns
200Type:FolioFolderRenamedThe rename202Type:FolioApprovalThe approval request; nothing has changed yet400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found409Type:Problemconflict,idempotency_conflict,idempotency_in_progressoridempotency_not_replayable413Type:Problemtoo_large421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl -X POST "https://api.unforged.sh/folio/folders/rename" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Content-Type: application/json" \
-d '{}' import requests
r = requests.post(
"https://api.unforged.sh/folio/folders/rename",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
json={},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/folio/folders/rename', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
body: JSON.stringify({}),
});
console.log(await res.json()); List folders
GET /folio/folders
Needs folio:records:read: See filed records, folders and metadata
The folders directly below parent (the top level when omitted), by path.
Parameters
parentqueryoptional Type:stringafterqueryoptional Type:stringThe previous page's
next_after.limitqueryoptional Type:integer
Returns
200Type:FolioFolderPageA page of folders400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl "https://api.unforged.sh/folio/folders" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.get(
"https://api.unforged.sh/folio/folders",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/folio/folders', {
method: 'GET',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json()); {
"folders": [
{
"path": "clients",
"matter": null,
"subject": null,
"protected": false,
"created_at_ms": 1790000000000
}
],
"next_after": null
} Create a folder
POST /folio/folders
Needs folio:records:write: File records, create folders, extend retention
Creates the folder and any missing ancestors. Its matter and subject are inherited by what is filed into it. No reason is needed; ledgered as folder.created. 409 if it exists.
Parameters
Idempotency-Keyheaderrequired Type:string1–255 printable ASCII characters, kept 24 hours.
Request body
pathrequired Type:stringmatteroptional Type:stringsubjectoptional Type:string
Returns
201Type:FolioFolderCreated400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found409Type:Problemconflict,idempotency_conflict,idempotency_in_progressoridempotency_not_replayable421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl -X POST "https://api.unforged.sh/folio/folders" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Content-Type: application/json" \
-d '{
"path": "clients/smith",
"matter": "M-1042"
}' import requests
r = requests.post(
"https://api.unforged.sh/folio/folders",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
json={
"path": "clients/smith",
"matter": "M-1042"
},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/folio/folders', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
body: JSON.stringify({
"path": "clients/smith",
"matter": "M-1042"
}),
});
console.log(await res.json()); A folder
GET /folio/folders/detail
Needs folio:records:read: See filed records, folders and metadata
One folder, with the number of filed records and folders directly in it.
Parameters
pathqueryrequired Type:string
Returns
200Type:FolioFolderDetailThe folder400Type:Probleminvalid_request,invalid_version,idempotency_key_requiredorinvalid_signature401Type:Problemunauthorized403Type:Problempermission_denied,org_suspended, oraddress_not_allowed(your organisation only accepts requests from the addresses it has listed)404Type:Problemnot_found421Type:Problemwrong_region429Type:Problemrate_limitedorquota_exceededdefaultType:Probleminternal
curl "https://api.unforged.sh/folio/folders/detail?path=<path>" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" import requests
r = requests.get(
"https://api.unforged.sh/folio/folders/detail?path=<path>",
headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
)
print(r.json()) const res = await fetch('https://api.unforged.sh/folio/folders/detail?path=<path>', {
method: 'GET',
headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14' },
});
console.log(await res.json());