Contents

Policies

Decide when a document goes to someone for review.

The LoupeSavedPolicy object

Attributes

  • policy required Type: LoupePolicy
  • created_by required Type: string

    Who saved this version.

  • created_at required Type: string

LoupeSavedPolicy on its own page

List saved policies

GET /loupe/policies

Needs loupe:checks:read: See document checks and their findings

The latest version of each policy you've saved.

Returns

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

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

Save a policy

POST /loupe/policies

Needs loupe:settings:manage: Loupe settings: webhooks

Saves the policy as the next version of its name; any version you send is replaced. Earlier versions stay as they were, so each check still shows the policy it ran under. Save one named default to use it for every check that doesn't pick a policy. Names are up to 60 lowercase letters, digits, - or _; anything you leave out takes our default.

Parameters

  • Idempotency-Key headerrequired Type: string

    1–255 printable ASCII characters, kept 24 hours.

Request body

LoupePolicy

  • name required Type: string
  • version required Type: integer
  • fail required Type: number
  • flag required Type: number
  • auto required Type: number
  • auto_approve required Type: boolean
  • weights optional Type: object

    How much each kind of finding counts, by the detector findings name; 1 unless given.

  • disabled optional Type: string[]

    Kinds of finding not to look for, by detector.

  • loupe_version optional Type: string

    The Loupe version checks under this policy run, such as 1.5.6. Left out, they run your organisation's version.

Returns

  • 201 Type: LoupeSavedPolicy
    Saved
  • 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 /loupe/policies · curl
curl -X POST "https://api.unforged.sh/loupe/policies" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "lenient",
  "version": 1,
  "fail": 0.95,
  "flag": 0.6,
  "auto": 0.15,
  "auto_approve": true,
  "weights": {},
  "disabled": []
}'
POST /loupe/policies · Python
import requests

r = requests.post(
    "https://api.unforged.sh/loupe/policies",
    headers={"Authorization": f"Bearer {UNFORGED_KEY}", "Unforged-Version": "2026-10-14"},
    json={
        "name": "lenient",
        "version": 1,
        "fail": 0.95,
        "flag": 0.6,
        "auto": 0.15,
        "auto_approve": True,
        "weights": {},
        "disabled": []
    },
)
print(r.json())
POST /loupe/policies · Node.js
const res = await fetch('https://api.unforged.sh/loupe/policies', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.UNFORGED_KEY}`, 'Unforged-Version': '2026-10-14', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "name": "lenient",
    "version": 1,
    "fail": 0.95,
    "flag": 0.6,
    "auto": 0.15,
    "auto_approve": true,
    "weights": {},
    "disabled": []
  }),
});
console.log(await res.json());

Get a saved policy

GET /loupe/policies/{name}

Needs loupe:checks:read: See document checks and their findings

The latest version, or the one asked for.

Parameters

  • name pathrequired Type: string

    The policy's name.

  • version queryoptional Type: integer

    A version other than the latest.

Returns

  • 200 Type: LoupeSavedPolicy
    The policy
  • 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 /loupe/policies/{name} · curl
curl "https://api.unforged.sh/loupe/policies/{name}" \
  -H "Authorization: Bearer $UNFORGED_KEY" \
  -H "Unforged-Version: 2026-10-14"
GET /loupe/policies/{name} · Python
import requests

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