Nib API
Check signatures against the references you hold.
api.unforged.sh- Version
2026-10-14 - nib.yaml
Quickstart
Your first check takes about five minutes. The commands carry your pinned version.
- 01Enrol a person’s reference signatures
- 02Check one document or a whole batch
- 03Read inline, by webhook, or as files
# 1 · enrol: a reference signature for your customer cust-88
curl -X PUT https://api.unforged.sh/nib/subjects/cust-88/references \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Idempotency-Key: enrol-cust-88-1" \
-F [email protected] # 2 · check: a document, with your own references
curl -X POST https://api.unforged.sh/nib/checks \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" \
-H "Idempotency-Key: app-1042" \
-F 'request={"process":"loan-application","items":[{"file":"q","subject_reference":"cust-88","reference":"APP-1042"}]};type=application/json' \
-F [email protected] # 3 · read: a queued job's status and results
curl https://api.unforged.sh/nib/checks/app-1042 \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" # find a check again by your reference
curl "https://api.unforged.sh/nib/checks?view=items&reference=APP-1042" \
-H "Authorization: Bearer $UNFORGED_KEY" \
-H "Unforged-Version: 2026-10-14" Your references
subject_reference- your id for the person · 1–128 of
A–Z a–z 0–9 . _ - reference- your id for the document · 1–128 characters
process- the workflow · 1–64 of
a–z 0–9 . _ - metadata- up to 20 string pairs · keys 1–40, values up to 500
They come back everywhere: the result, the job, the stream, webhooks and bucket files.
Drop files in nib/inbox/<job>/, write manifest.json last.
The answer lands in nib/results/<job>/.
# any S3 tool, with your bucket's keys: the files first, the manifest last
aws s3 cp ./batch/ s3://$UNFORGED_BUCKET/nib/inbox/2026-10-batch-07/ --recursive
aws s3 cp manifest.json s3://$UNFORGED_BUCKET/nib/inbox/2026-10-batch-07/manifest.json
# nib/inbox/2026-10-batch-07/manifest.json
{
"items": [
{
"file": "app-1041.pdf",
"subject_reference": "cust-88",
"template_id": "benefits-form-v3",
"reference": "APP-1041"
},
{
"file": "app-1042.jpg",
"references": [
"refs/extra-1042.png"
],
"target": {
"page": 1,
"box": "applicant_signature"
},
"reference": "APP-1042",
"metadata": {
"branch": "leeds"
}
}
],
"policy": "default",
"process": "loan-application"
}
# the answer: nib/results/2026-10-batch-07/summary.json
# (one result per line in nib/results/2026-10-batch-07/results.ndjson)
{
"job_id": "inv-2291",
"status": "completed",
"total": 2,
"completed": 1,
"failed": 1,
"counts": {
"APPROVE": 1
},
"errors": [
{
"item_index": 1,
"file": "missing.png",
"field": null,
"type": "file_not_found",
"detail": "missing.png is not in the job folder"
}
],
"metadata": {
"batch": "2026-10"
},
"versions": {
"model": "nib-2.6",
"policy": "default@7",
"api_version": "2026-09-27"
},
"started_at": "2026-09-25T10:15:30.123Z",
"completed_at": "2026-09-25T10:15:32.456Z"
} One result per item: the same JSON inline, from GET, streamed, and in your
bucket. See CheckResult.
{
"id": "ver_01j9x3m8v7k2q4r5s6t7u8v9w0",
"item_index": 0,
"kind": "check",
"file": "questioned",
"subject_reference": "cust-88",
"reference": "APP-1042",
"process": "loan-application",
"metadata": {
"branch": "leeds"
},
"status": "completed",
"error": null,
"decision": "APPROVE",
"input_type": "photo",
"pages": 1,
"notes": [],
"signatures": [
{
"index": 0,
"page": 1,
"bbox": [
412,
1880,
498,
160
],
"located_by": "template",
"quality": {
"ok": true,
"effective_dpi": 214,
"sharpness": 812.5,
"contrast": 180,
"issues": []
},
"match_probability": 0.94,
"band": [
0.88,
0.97
],
"reference_count": 2,
"per_reference": [
{
"ref": "ref_01j9x3m8v7k2q4r5s6t7u8v9w1",
"probability": 0.95
},
{
"ref": "ref_01j9x3m8v7k2q4r5s6t7u8v9w2",
"probability": 0.92
}
],
"flags": [],
"decision": "APPROVE",
"reasons": [
"Compared against 2 references",
"Overall appearance is within this writer's usual range",
"Shape alignment is within this writer's usual range",
"Approved, not auto-approved: the lowest likely score (88.0%) is under the auto-approve bar (97.0%), and auto-approve is off in policy default@7"
],
"best_match": true
}
],
"anchor_probability": 0.94,
"signer_match": null,
"versions": {
"model": "nib-2.6",
"policy": "default@7",
"api_version": "2026-09-27"
},
"input_hashes": {
"questioned": "sha256:8550d9b6affca27a5645d75b058479d2e081b16a135e2d4255e5e83714ebf987",
"references": [
"sha256:070a8e98f85afe04ba05542428664ec3684db24bc356133c11d41f9fab27f135",
"sha256:1cf1da50e3f0be0b50197022be0eedf20fa688cf20ca1154b388098a9d2e29e1"
]
},
"timings_ms": {
"total": 1840
}
} Signed with Unforged-Signature, rendered in your pinned version (Unforged-Version). Retried with backoff for 24 hours.
job.completedjob.failedreference.enrolledreference.rejected
POST /your/webhook HTTP/1.1
Content-Type: application/json
Unforged-Signature: t=1790000000,v1=5f2c…
Unforged-Version: 2026-10-14
Unforged-Event-Id: evt_01j9x3m8v7k2q4r5s6t7u8v9w0
{
"id": "evt_01j9x3m8v7k2q4r5s6t7u8v9w0",
"type": "job.completed",
"created_at": "2026-09-25T10:15:30.123Z",
"data": {
"job_id": "inv-2291",
"status": "completed",
"total": 1,
"counts": {
"APPROVE": 1
},
"failed": 0,
"items": [
{
"id": "ver_01j9x3m8v7k2q4r5s6t7u8v9w0",
"item_index": 0,
"kind": "check",
"file": "questioned",
"subject_reference": "cust-88",
"reference": "APP-1042",
"process": "loan-application",
"metadata": {
"branch": "leeds"
},
"status": "completed",
"error": null,
"decision": "APPROVE",
"input_type": "photo",
"pages": 1,
"notes": [],
"signatures": [],
"anchor_probability": 0.94,
"signer_match": null,
"versions": {
"model": "nib-2.6",
"policy": "default@7",
"api_version": "2026-09-27"
},
"input_hashes": null,
"timings_ms": {
"total": 1840
}
}
],
"items_truncated": false,
"versions": {
"model": "nib-2.6",
"policy": "default@7",
"api_version": "2026-09-27"
},
"status_url": "/nib/checks/inv-2291"
}
}
# verify: HMAC-SHA256 of "<t>.<raw body>" with your whsec_ secret equals v1 - 01Add a custom connector with
https://api.unforged.sh/mcp - 02Sign in and choose your organisation
- 03Ask about your records, checks and queue
With an API key instead of signing in:
claude mcp add --transport http unforged https://api.unforged.sh/mcp \
--header "Authorization: Bearer $UNFORGED_API_KEY" The whole integration
-
PUT /nib/subjects/{subject_reference}/referencesEnrol references, with where each came from.
-
POST /nib/checksOne document answers inline. A batch returns a job.
-
GET /nib/checks/{job_id}Status and results, paged or streamed as NDJSON.
-
WebhooksSigned. Retried with backoff for 24 hours.
Resources
Checks
Check documents and read results.
Subjects
Enrolled people and their reference signatures.
- GET
/nib/subjects - GET
/nib/subjects/{subject_reference} - DELETE
/nib/subjects/{subject_reference} - PUT
/nib/subjects/{subject_reference}/references - DELETE
/nib/subjects/{subject_reference}/references/{ref_id} - GET
/nib/subjects/{subject_reference}/references/{ref_id}/image - POST
/nib/subjects/{subject_reference}/references/unlearn - DELETE
/nib/subjects/{subject_reference}/references/unlearn
- GET
Sessions
Short-lived tokens for end-user apps.
Live capture
Live capture guidance over a WebSocket.
Policies and settings
Policies, templates and bucket keys.
- GET
/nib/policies - GET
/nib/policies/{name} - PUT
/nib/policies/{name} - GET
/nib/templates - POST
/nib/templates - GET
/nib/templates/{template_id} - DELETE
/nib/templates/{template_id} - GET
/nib/bucket-keys - POST
/nib/bucket-keys - DELETE
/nib/bucket-keys/{id} - GET
/nib/settings/retention - PUT
/nib/settings/retention - GET
/nib/settings/learning - PUT
/nib/settings/learning
- GET
Webhook endpoints
Webhook endpoints and their delivery log.
Usage
The month's usage and estimated charge.
Webhook events
job.completedjob.failedreference.enrolledreference.rejectedwebhook.test