Skip to content

PAM API

This reference covers the Privileged Access Management (PAM) REST surface: the admin control plane under /api/v1/pam, the device actuation endpoint, and the agent-side ingest endpoint. For the administrative workflow these endpoints back, see Privileged Access Management; for the trust model, see the PAM Security Model.

All paths are relative to the API base URL and version prefix (/api/v1). See the API Overview for authentication, base URL, and common conventions.

The /pam/* control-plane endpoints require a JWT bearer token (or API key) and run under organization, partner, or system scope. Authorization maps to the device permission set:

Operation classPermissionExtra gate
Read (list, active, rules)devices:read
Rule create / update / deletedevices:writeMFA
Approve / deny / revokedevices:executeMFA

Tenant isolation is enforced by row-level security on every query. Site-restricted technicians are additionally narrowed to their allowed sites: requests outside those sites are filtered from reads and rejected on writes with 403.


MethodPathDescription
GET/pam/elevation-requestsList and filter elevation requests (Requests and Audit tabs).
GET/pam/activeList currently-active (unexpired, approved) elevations.
POST/pam/elevation-requests/:id/respondApprove or deny a pending request.
POST/pam/elevation-requests/:id/revokeRevoke an active elevation before it expires.

GET /pam/elevation-requests

Query parameters (all optional):

ParamTypeNotes
statusenumpending, approved, auto_approved, denied, expired, revoked, actuating
flowTypeenumuac_intercept, tech_jit_admin, ai_tool_action
deviceIduuidFilter to one device
siteIduuidFilter to one site (must be within the caller’s site scope)
from / toISO-8601Bound by request time
page / limitintlimit max 100, default 50

Response:

{
"success": true,
"requests": [
{
"id": "",
"orgId": "",
"deviceId": "",
"deviceHostname": "WIN-ACCT-04",
"siteName": "HQ",
"flowType": "uac_intercept",
"status": "pending",
"subjectUsername": "acme\\sarah",
"targetExecutablePath": "C:\\Users\\sarah\\Downloads\\FirefoxSetup.exe",
"targetExecutableSigner": "Mozilla Corporation",
"requestedAt": "2026-06-13T14:02:11Z",
"approvedByName": null,
"deniedByName": null,
"revokedByName": null,
"matchedPolicyName": null,
"pamRuleId": null,
"pamRuleName": null,
"decisionSource": null
}
],
"pagination": { "page": 1, "limit": 50, "total": 1 }
}

decisionSource is derived: software_policy, pam_rule, human, or null (still pending). AI tool-action rows additionally carry toolName, riskTier, and actionDigest.

GET /pam/active

Returns up to 500 elevations whose status is approved, auto_approved, or actuating and whose expiresAt is in the future. No query parameters. Used to render the live “active windows” view with expiry countdowns.

{ "success": true, "active": [ { "id": "", "expiresAt": "2026-06-13T14:17:00Z", "…": "" } ] }

POST /pam/elevation-requests/:id/respond — requires devices:execute + MFA.

Request body:

{
"decision": "approve",
"reason": "Approved per change CHG-1042",
"durationMinutes": 30
}
FieldTypeNotes
decisionenumapprove or deny (required)
reasonstringOptional on approve, recommended on deny; max 2000 chars
durationMinutesintApproval window, 1–1440 (24h max). Defaults to 15

Only a pending request can be decided. The transition is an atomic compare-and-swap on pending, so concurrent decisions are safe.

StatusMeaning
200{ "success": true, "id": "…", "status": "approved" | "denied" }
400Invalid id or body
403Site access denied, or MFA not satisfied
404Request not found (or outside the caller’s org)
409Request is no longer pending (lost the race), or a linked AI tool execution already timed out

POST /pam/elevation-requests/:id/revoke — requires devices:execute + MFA.

Ends an active elevation early.

{ "reason": "Maintenance window cancelled" }

reason is required (1–2000 chars). Only an active elevation (approved, auto_approved, or actuating) can be revoked; a stale or already-finished row returns 409.

{ "success": true, "id": "", "status": "revoked" }

MethodPathDescription
GET/pam/rulesList rules in priority order.
POST/pam/rulesCreate a rule.
POST/pam/rules/previewDry-run draft criteria against request history.
PATCH/pam/rules/:idUpdate a rule.
DELETE/pam/rules/:idDelete a rule.

POST /pam/rules (create) and PATCH /pam/rules/:id (partial update) — require devices:write + MFA.

{
"name": "Auto-approve signed Mozilla installers",
"verdict": "auto_approve",
"priority": 50,
"enabled": true,
"matchSigner": "Mozilla Corporation",
"approvalDurationMinutes": 30,
"siteId": null
}
FieldTypeNotes
namestringRequired, 1–255 chars
verdictenumauto_approve, auto_deny, require_approval, ignore
priorityintLower runs first; default 100
enabledboolDefault true
siteIduuid | nullNarrow to one site; null = org-wide
matchSignerstringCode-signer (executable rule)
matchHashstringSHA-256 hex digest (executable rule)
matchPathGlobstringFile-path glob (executable rule)
matchParentImagestringParent process (executable rule)
matchUserstringNarrow by requesting user
matchAdGroupstringNarrow by AD group
matchToolNamestringAI tool name (tool-action rule)
matchRiskTierintRisk tier 0–4 (tool-action rule)
timeWindowobject{ start, end, days?, timezone? }, HH:MM 24h, days 0–6 (Sun–Sat)
approvalDurationMinutesint1–1440; null falls back to the org default

Rule-shape validation (enforced on create and on the merged result of an update):

  • A rule must carry at least one identifying criterion (signer/hash/path/parent/user/group/tool/tier). A rule scoped only by time window — or nothing — is rejected with 400.
  • A rule is either executable-shaped (signer/hash/path/parent) or tool-action-shaped (tool name / risk tier). Mixing the two is rejected, because no single observation carries both.
  • verdict: "ignore" is not valid for tool-action rules — a tool action must be decided.

Create returns 201 with the full rule; update returns 200.

POST /pam/rules/preview — requires devices:write.

Dry-runs draft criteria against historical requests so you can see what a rule would have matched before saving it. Accepts the same criteria fields as a rule, plus windowDays (1–90, default 30) and an optional flowType.

{
"success": true,
"totalMatched": 12,
"totalScanned": 480,
"windowDays": 30,
"truncated": false,
"statusBreakdown": { "pending": 2, "approved": 7, "auto_approved": 3, "denied": 0, "expired": 0, "revoked": 0, "actuating": 0 },
"sample": [ { "id": "", "requestedAt": "", "flowType": "uac_intercept", "status": "approved" } ]
}

The preview is a pure per-rule match — it does not replay priority shadowing or the software-policy bridge. Historical rows do not store AD groups, so any draft containing matchAdGroup reports zero matches.


MethodPathDescription
POST/devices/:id/actuate-elevationQueue an actuate_elevation command for an approved UAC elevation.

POST /devices/:id/actuate-elevation — organization/partner/system scope, devices:execute, MFA.

Queues the agent “go” signal for a consent.exe prompt that is already waiting on the user’s screen. The command payload that reaches the agent carries only the elevation request id and a timeout — the dormant-admin credential is minted locally by the agent and never crosses the wire.

{ "elevationRequestId": "", "timeoutMs": 8000 }

The route is single-use: it atomically transitions the request from approved to actuating in the same transaction that queues the command. A request that is not approved, or that another caller already claimed, is refused.

StatusMeaning
201Command queued; returns the command id and elevationRequestId
400Invalid body, or device decommissioned
403PAM actuator disabled, site access denied, or MFA not satisfied
404Device or elevation request not found
409Request not approved (wrong_status) or already being actuated (race_lost)

MethodPathDescription
POST/agents/:id/elevation-requestsAgent reports an observed UAC consent prompt.

This endpoint is called by the agent, authenticated with the agent bearer token (not a user JWT), and is documented here for completeness. It records a UAC observation as an elevation_requests row with flowType: uac_intercept, runs the decisioning chain (software-policy bridge → PAM rules → pending), and emits the corresponding event and audit rows.

Request body (synthesized fields like reason are written server-side; the agent only sends discovery data):

{
"subject_username": "acme\\sarah",
"target_executable_path": "C:\\Users\\sarah\\Downloads\\FirefoxSetup.exe",
"target_executable_hash": "<agent-reported file hash>",
"target_executable_signer": "Mozilla Corporation",
"pid": 4812,
"parent_image": "C:\\Windows\\explorer.exe",
"command_line": "",
"observed_at": "2026-06-13T14:02:11Z"
}
StatusMeaning
201{ "id": "…", "status": "pending" | "auto_approved" | "denied" }
200{ "id": null, "status": "ignored" } — an ignore rule matched; no request row is created
413Body exceeds 32 KB
429Per-device rate limit exceeded (about 10 requests/second)

Decisioning fails safe: if either evaluator errors, the request is recorded as pending rather than auto-approved.


Configuration policy: enabling UAC capture

Section titled “Configuration policy: enabling UAC capture”

Whether a device captures UAC prompts at all is governed by the pam configuration-policy feature, resolved through the normal policy hierarchy (partner → org → site → group → device, closest-wins). The feature’s inline settings shape is a single flag:

{ "uacInterceptionEnabled": true }

uacInterceptionEnabled defaults to true at every level, so upgrades are behavior-preserving; admins opt a scope out by assigning a policy that turns it off. This toggle controls only whether devices capture elevation prompts — it does not govern the rule chain, request queue, or audit history, which are scoped to the organization and site and managed in the Privileged Access console. See Configuration Policies for how feature settings resolve.