Basics
What every Unforged API shares: keys, versions, headers and errors.
API keys and permissions
Call https://api.unforged.sh with Authorization: Bearer <API key>. A key carries a set of permissions, chosen
from your own when you create it, and each endpoint says which one it needs.
org:readSee org, members, usageorg:members:manageInvite/remove members, assign rolesorg:sso:manageAdmin Portal links: SSO, directory sync, role mappingorg:keys:manageCreate/revoke API keys (within own permissions)org:billing:manageCheckout, billing portal, planorg:settings:manageRetention, org-wide settings, the API version pinorg:audit:readAudit logorg:children:accessAct in descendant orgsorg:children:manageCreate/suspend child orgsnib:checks:createSubmit checks, sessions, livenib:checks:readRead checks and resultsnib:subjects:readRead subjects/references metadata and thumbnailsnib:references:writeEnroll references, confirm-to-learnnib:references:deleteDelete references and subjects, unlearnnib:settings:managePolicy, learning, templates, webhooks, bucket keysfolio:records:readSee filed records, folders and metadatafolio:documents:readOpen and download documents (a reason is recorded)folio:documents:searchSearch record metadata and document text (audited)folio:records:writeFile records, create folders, extend retentionfolio:records:deleteRequest disposal and early deletionfolio:holds:managePlace and request release of legal holdsfolio:holds:approveApprove hold releases and early deletion (second person)folio:exports:createCreate exports, custody and integrity reportsfolio:audit:readRead the folio ledgerfolio:settings:manageRetention classes, reason settings, protected folders, webhookssig:packages:readSee packages, their signers and signed filessig:packages:sendCreate, send, correct and void packagessig:settings:manageSig settings: Folio filing and Nib checksloupe:checks:createSend documents to be checked for forgeryloupe:checks:readSee document checks and their findingsloupe:checks:reviewRecord the decision on a document checkloupe:settings:manageLoupe settings: webhooks
Versions
Current version2026-10-14
- Send
Unforged-Version: 2026-10-14to choose a version per request. Without it your organisation’s pin applies. - Additive changes (new endpoints, optional parameters, response fields) never make a version. Ignore fields you don’t know.
- Breaking changes ship only in a new dated version.
- A version stays supported for 24 months after a newer one replaces it.
- Deprecated versions answer with
Deprecation,SunsetandLinkheaders.
Headers
AuthorizationBearer <API key>on every route that needs a key.Unforged-VersionAPI version (
YYYY-MM-DD) for this request; defaults to your pinned version.Unforged-OrgAct in a child organisation (its id). Needs
org:children:access.Idempotency-KeyOn a POST, the same key and body give back the first answer for 24 hours.
Errors
An error comes back as application/problem+json with a status, a sentence you can
show, and a code that stays the same, so match on the code.
typerequired Type:stringhttps://unforged.sh/problems/<code>titlerequired Type:stringstatusrequired Type:integerdetailrequired Type:stringcoderequired Type:stringA stable error code.
request_idoptional Type:stringregionoptional Type:stringOn
wrong_region, your home region.api_hostoptional Type:stringOn
wrong_region, that region's API host.addressoptional Type:stringOn
address_not_allowed, the address your request came from.terms_versionoptional Type:stringOn
learning_terms_required, the version to accept.job_idoptional Type:stringOn
busyortimeoutof a check that continues.status_urloptional Type:stringhostoptional Type:stringOn a failed URL fetch, the host.
reasonoptional Type:stringOn a failed URL fetch, why (e.g.
http_status,timeout). Onorg_suspended,idlewhen the organisation was removed for inactivity (it can start again).checksoptional Type:objectOn
not_ready.errorsoptional Type:any[]On a synchronous check whose job failed.
Every code
access_suspendedaddress_not_allowedawaiting_first_paymentbilling_already_activebilling_requiredbusyconflictfetch_failedidempotency_conflictidempotency_in_progressidempotency_key_requiredidempotency_not_replayableinternalinvalid_requestinvalid_signatureinvalid_versionlearning_terms_requiredmethod_not_allowednot_allowlistednot_available_in_devnot_foundnot_implementednot_readyorg_movingorg_suspendedpermission_deniedquota_exceededrate_limitedreason_requiredstorage_provisioningtenant_not_provisionedtimeouttoo_largeunsupported_mediawebhook_test_failedwrong_region