Contents

Webhook endpoints

Hear when something happens to your records.

The FolioWebhook object

Attributes

  • id required Type: string
  • url required Type: string
  • events required Type: string[]
  • created_at required Type: string

FolioWebhook on its own page

List folio's webhook endpoints

GET /folio/webhooks

Needs folio:settings:manage: Retention classes, reason settings, protected folders, webhooks

folio's endpoints only; Nib's are listed by GET /nib/webhooks.

Returns

  • 200 Type: FolioWebhookList
    The endpoints
  • 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/webhooks · curl
curl "https://api.unforged.sh/folio/webhooks" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14"
GET /folio/webhooks · Python
import requests

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

Create a folio webhook endpoint

POST /folio/webhooks

Needs folio:settings:manage: Retention classes, reason settings, protected folders, webhooks

Like POST /nib/webhooks (the same signing, retries, delivery log and connection test), for folio's events: folio.record.filed, folio.hold.applied, folio.hold.released, folio.record.disposed, folio.integrity.alert, folio.export.ready, folio.restore.ready. The secret is shown once. No Idempotency-Key: a retry creates another endpoint.

Request body

FolioWebhookCreate

  • url required Type: string
  • events required Type: "folio.record.filed" "folio.hold.applied" "folio.hold.released" "folio.record.disposed" "folio.integrity.alert" "folio.export.ready" "folio.restore.ready"[]

Returns

  • 201 Type: FolioWebhookCreated
    Created
  • 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
  • 409 Type: Problem
    conflict, idempotency_conflict, idempotency_in_progress or idempotency_not_replayable
  • 421 Type: Problem
    wrong_region
  • 429 Type: Problem
    rate_limited or quota_exceeded
  • default Type: Problem
    internal
POST /folio/webhooks · curl
curl -X POST "https://api.unforged.sh/folio/webhooks" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://hooks.example.com/folio",
  "events": [
    "folio.record.filed"
  ]
}'
POST /folio/webhooks · Python
import requests

r = requests.post(
    "https://api.unforged.sh/folio/webhooks",
    headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
    json={
        "url": "https://hooks.example.com/folio",
        "events": [
            "folio.record.filed"
        ]
    },
)
print(r.json())
POST /folio/webhooks · Node.js
const res = await fetch('https://api.unforged.sh/folio/webhooks', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "url": "https://hooks.example.com/folio",
    "events": [
      "folio.record.filed"
    ]
  }),
});
console.log(await res.json());

Delete a folio webhook endpoint

DELETE /folio/webhooks/{webhook_id}

Needs folio:settings:manage: Retention classes, reason settings, protected folders, webhooks

404 for an unknown endpoint and for a Nib endpoint.

Parameters

  • webhook_id pathrequired Type: string

Returns

  • 204
    Deleted
  • 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
DELETE /folio/webhooks/{webhook_id} · curl
curl -X DELETE "https://api.unforged.sh/folio/webhooks/{webhook_id}" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14"
DELETE /folio/webhooks/{webhook_id} · Python
import requests

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