devices
Device posture tells policies which registered device a request comes from and whether an MDM or EDR finds it compliant.
Device posture tells policies which registered device a request comes from and whether an MDM or EDR finds it
compliant. A browser or agent enrolls a public key once, then sends a short-lived signed proof with its requests in
the x-better-iam-device header. The proof is bound to the session it travels with. Decisions check it against the
enrolled key and expose request.deviceAssurance, request.deviceManaged, request.deviceCompliant,
request.deviceId and request.devicePlatform. Integrations report the devices they manage and their posture, and
the tenant's requirements decide which of them are compliant. Registered devices are not remembered devices
("remember this device" at sign-in): they never satisfy MFA. The guide is
Device posture, and the browser and Node
helper is @better-iam/client/device.
Assurance levels
Every request gets one level, weakest first:
none: no proof, or one that did not verify. A bad proof is never an error.registered: a verified proof from an active device that no active integration manages.managed: the device is reported by an active integration but misses a requirement.compliant: a managed device that meets every requirement of the tenant (see configure).
A proof is a compact JWS whose protected header holds only alg, typ (device-proof+jwt) and kid (the RFC 7638
thumbprint of an enrolled key), with iat within 300 seconds of the server clock and sid equal to the id of the
session that authenticated the request. The algorithm is pinned by the stored key (ES256 for EC P-256, EdDSA for
Ed25519), and a header carrying key material (jwk, jku, x5u, x5c) or crit is refused. The device must be
active, in the identity's home tenant, and shared or owned by the identity.
Who may call what
People manage their own devices without a permission: enroll, mine and retireMine from their own sign-in session
or API key in the tenant, and check from any session of the tenant. Administrators hold iam:devices:read or
iam:devices:manage on iam/devices, iam/devices/{id}, iam/devices/enrollments, iam/devices/settings and
iam/devices/integrations/{id}. Every iam:devices:manage call except listEnrollments and revokeEnrollment
needs a recent sign-in. Integrations call report with iam:devices:report on their own
iam/devices/integrations/{id}, usually through a service account's API key.
| Method | What it does | Access |
|---|---|---|
check | Reports what the device presenting this request proves: its assurance, id, platform and compliance. | Credential |
configure | Sets the requirements a managed device must meet to be compliant. | Credential |
createEnrollment | Creates a one-time enrollment code that binds a browser or agent key to a device, usually one an integration manages. | Credential |
createIntegration | Adds an MDM or EDR integration that can report devices and their posture. | Credential |
delete | Deletes a device with its keys and enrollment codes. | Credential |
deleteIntegration | Deletes an integration, optionally leaving the devices it manages unmanaged. | Credential |
enroll | Enrolls a public key for the caller's browser or agent, creating their device or binding the key to a device with an enrollment code. | Credential |
get | Returns one device with its enrolled keys. | Credential |
getSettings | Returns the tenant's compliance requirements, or the defaults until they are configured. | Credential |
list | Lists the tenant's devices, newest first, each with its compliance, assurance, key count and owner. | Credential |
listEnrollments | Lists the tenant's enrollment codes, newest first, without the codes themselves. | Credential |
listIntegrations | Lists the tenant's MDM and EDR integrations by name, with the number of devices each manages. | Credential |
mine | Lists the caller's devices that are not retired, each with its compliance and assurance, the device presenting this request first. | Credential |
removeKey | Removes one enrolled key from a device, such as a lost browser profile or a replaced agent. | Credential |
report | Creates or updates up to 500 devices with their posture, as reported by an integration, all or nothing. | Credential |
retire | Retires a device for good, deleting its keys and pending enrollment codes. | Credential |
retireMine | Retires one of the caller's own unmanaged devices and deletes its keys. | Credential |
revokeEnrollment | Withdraws an enrollment code, used or not. | Credential |
update | Renames a device, changes its owner, or marks it lost or active again. | Credential |
updateIntegration | Renames an integration, disables or enables it, or changes whether the vendor's verdict counts. | Credential |
check
Reports what the device presenting this request proves: its assurance, id, platform and compliance.
Used inDevice posture
- Permission: Any session of the tenant.
- Audited as: Not audited. It records when the device and key were last seen, at most once a minute.
- Errors:
ACCESS_DENIEDfor a session of another tenant.
proof is absent (no header), invalid (the proof did not verify: an unknown or removed key, another session, a
clock more than five minutes off, a lost or retired device) or verified. For a verified device reasons explains
why it is not compliant (not-managed, stale, not-encrypted, os-too-old and so on). Call it after sign-in to
decide whether to offer enrollment.
const status = await client.devices.check({ tenantId });
// { assurance: 'registered', deviceId, platform: 'macos', managed: false, compliant: false,
// reasons: ['not-managed'], proof: 'verified' }Prop
Type
A DeviceCheck object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/check" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.check(
credential: CredentialInput,
input: { tenantId: string },
): Promise<DeviceCheck>configure
Sets the requirements a managed device must meet to be compliant.
Used inDevice posture
- Permission:
iam:devices:manageoniam/devices/settings, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:settingswith the requirements before and after. - Errors:
INVALID_INPUTfor an unknown field, a flag that is not a boolean, an unknown platform or a minimum that is not a dotted version inminOsVersions, or amaxCheckInAgeHoursoutside 1 to 720;RECENT_AUTH_REQUIRED.
requireEncrypted, requireScreenLock, requireFirewall and requireEdr need the posture field reported true
(unknown fails). blockJailbroken (on by default) fails a device reported jailbroken. minOsVersions sets a minimum
per platform (a device with an unknown version then fails), and maxCheckInAgeHours (24 by default) fails devices
whose last check-in is older. An integration with trustVendorCompliance also fails devices its vendor calls
non-compliant. Fields left out keep their values; minOsVersions replaces the whole map. Compliance is worked out at
decision time, so the new requirements apply to the next request.
await iam.api.devices.configure(credential, {
tenantId,
requireEncrypted: true,
requireScreenLock: true,
minOsVersions: { macos: '14.0', windows: '10.0.19045' },
maxCheckInAgeHours: 12,
});Prop
Type
A DeviceSettingsView object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/configure" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.configure(
credential: CredentialInput,
input: {
tenantId: string;
requireEncrypted?: boolean;
requireScreenLock?: boolean;
requireFirewall?: boolean;
requireEdr?: boolean;
blockJailbroken?: boolean;
minOsVersions?: Partial<Record<DevicePlatform, string>>;
maxCheckInAgeHours?: number;
},
): Promise<DeviceSettingsView>createEnrollment
Creates a one-time enrollment code that binds a browser or agent key to a device, usually one an integration manages.
Used inDevice posture
- Permission:
iam:devices:manageoniam/devices/enrollments(and, withdeviceId, oniam/devices/{id}too, since using the code adds a key to that device), and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:enrollment-create(never the code). - Errors:
ACCESS_DENIEDwithoutiam:devices:manageon the device named bydeviceId;INVALID_INPUTfor anexpiresInMsoutside 10 minutes to 30 days, an owner who is not a person of the tenant, or an owner other than the device's;INVALID_TRANSITION(409) when the device is not active;LIMIT_EXCEEDED(409) past 1000 pending codes in the tenant;NOT_FOUNDfor a device outside the tenant;RECENT_AUTH_REQUIRED.
The code (biam_denr_…) appears only in this answer and is stored as a hash. It lasts 7 days unless expiresInMs
says otherwise and works once. With deviceId, enrollment binds the key to that device; a device with an owner limits
the code to that person, as ownerIdentityId does. Deliver the code to the machine through the MDM, where the app
passes it to enroll after the person signs in.
const { code, expiresAt, enrollmentId } = await iam.api.devices.createEnrollment(credential, {
tenantId,
deviceId: managedDeviceId,
ownerIdentityId: aliceId,
expiresInMs: 24 * 3_600_000,
});Prop
Type
A DeviceEnrollmentCode object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/createEnrollment" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.createEnrollment(
credential: CredentialInput,
input: {
tenantId: string;
deviceId?: string;
ownerIdentityId?: string;
expiresInMs?: number;
},
): Promise<DeviceEnrollmentCode>createIntegration
Adds an MDM or EDR integration that can report devices and their posture.
Used inDevice posture
- Permission:
iam:devices:manageoniam/devices/integrations, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:integration-create. - Errors:
INVALID_INPUTfor an unknown vendor or field;CONFLICT(409) for a name in use (ignoring case);LIMIT_EXCEEDED(409) past 20 integrations;RECENT_AUTH_REQUIRED.
vendor is intune, jamf, kandji, workspace-one, google-endpoint, crowdstrike, sentinelone or custom.
trustVendorCompliance (default true) counts the vendor's own verdict next to the tenant's requirements. Give the
connector a service account allowed iam:devices:report on iam/devices/integrations/{id} for the new id, and an API
key scoped to that action.
Prop
Type
A DeviceIntegrationView object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/createIntegration" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"name": "<name>",
"vendor": "intune"
}'iam.api.devices.createIntegration(
credential: CredentialInput,
input: {
tenantId: string;
name: string;
vendor: DeviceIntegrationVendor;
trustVendorCompliance?: boolean;
},
): Promise<DeviceIntegrationView>delete
Deletes a device with its keys and enrollment codes.
- Permission:
iam:devices:manageoniam/devices/{id}, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:delete. - Errors:
RECENT_AUTH_REQUIRED;NOT_FOUND.
A managed device comes back with the integration's next report, as a new record without keys. Use retire to keep it
out.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/delete" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"deviceId": "<deviceId>"
}'iam.api.devices.delete(
credential: CredentialInput,
input: { tenantId: string; deviceId: string },
): Promise<{ success: true; keysRemoved: number; enrollmentsRemoved: number }>deleteIntegration
Deletes an integration, optionally leaving the devices it manages unmanaged.
- Permission:
iam:devices:manageoniam/devices/integrations/{id}, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:integration-deletewith the number of devices detached. - Errors:
RESOURCE_IN_USE(409) while it manages devices, unlessdetach: true;NOT_FOUND;RECENT_AUTH_REQUIRED.
Detached devices keep their keys and last posture but no longer count as managed, so they drop to registered.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/deleteIntegration" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"integrationId": "<integrationId>"
}'iam.api.devices.deleteIntegration(
credential: CredentialInput,
input: { tenantId: string; integrationId: string; detach?: boolean },
): Promise<{ success: true; detached: number }>enroll
Enrolls a public key for the caller's browser or agent, creating their device or binding the key to a device with an enrollment code.
Used inDevice posture
- Permission: None beyond a person's own sign-in session or API key in the tenant, with a recent sign-in; never
while impersonating. The request must carry a device proof (
x-better-iam-device) signed with the key being enrolled, for this session, which proves the caller holds the key. - Audited as:
device:enroll. - Errors:
INVALID_INPUTfor a key that is not a public EC P-256 or Ed25519 JWK (private members are refused outright), a missing proof or one not made with the key for this session, an unknown platform, an invalid, used or expired enrollment code, or a caller that is not a person;CONFLICT(409) when the key is already enrolled;ACCESS_DENIEDfrom another kind of session or another tenant, or with a code or device that belongs to someone else;IMPERSONATION_RESTRICTED;RECENT_AUTH_REQUIRED;LIMIT_EXCEEDED(409) past 20 devices per person or 20 keys per device;INVALID_TRANSITION(409) when the code's device is not active;RATE_LIMITEDafter 30 attempts by one person in a rate-limit window.
Without enrollmentCode the call registers a new unmanaged device owned by the caller. With a code from
createEnrollment it binds the key to the code's device (then name and platform are
ignored) or, when the code names no device, creates one owned by the code's person, or shared when the code names
nobody. The code is used up. keyId is the key's thumbprint, the kid of its proofs. The result's device has
current: true when this request already carries a valid proof from it.
import { createDeviceProver } from 'better-iam/client/device';
const prover = createDeviceProver();
const { device, keyId } = await client.devices.enroll({
tenantId,
name: 'Work laptop',
platform: 'macos',
publicKey: await prover.publicJwk(),
});A DeviceEnrollInput object:
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/enroll" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"name": "<name>",
"platform": "other",
"publicKey": {}
}'iam.api.devices.enroll(
credential: CredentialInput,
input: DeviceEnrollInput,
): Promise<{ device: MyDevice; keyId: string }>get
Returns one device with its enrolled keys.
- Permission:
iam:devices:readoniam/devices/{id}. - Audited as:
iam:devices:read. - Errors:
NOT_FOUNDwhen the device is not in this tenant.
publicKeys lists each key's thumbprint, algorithm (ES256 or EdDSA), who enrolled it and when, and when a
verified proof from it was last seen.
Prop
Type
A DeviceDetail object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/get" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"deviceId": "<deviceId>"
}'iam.api.devices.get(
credential: CredentialInput,
input: { tenantId: string; deviceId: string },
): Promise<DeviceDetail>getSettings
Returns the tenant's compliance requirements, or the defaults until they are configured.
- Permission:
iam:devices:readoniam/devices/settings. - Audited as:
iam:devices:read.
configured is false while the tenant uses the defaults: nothing required except that jailbroken devices fail, and a
check-in within 24 hours.
Prop
Type
A DeviceSettingsView object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/getSettings" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.getSettings(
credential: CredentialInput,
input: { tenantId: string },
): Promise<DeviceSettingsView>list
Lists the tenant's devices, newest first, each with its compliance, assurance, key count and owner.
- Permission:
iam:devices:readoniam/devices. - Audited as:
iam:devices:read. - Errors:
INVALID_INPUTfor an unknown status or platform, alimitoutside 1 to 1000, or anoffsetoutside 0 to 1000000.
Filter by ownerIdentityId, status, platform, managed and compliant, and search with query (device id,
name, serial number, model, the integration's device id, and the owner's name or email, case-insensitive). total
counts every match before paging. assurance is what a proof from the device would get now: none while it has no
key or is not active.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/list" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.list(
credential: CredentialInput,
input: {
tenantId: string;
ownerIdentityId?: string;
status?: DeviceStatus;
managed?: boolean;
compliant?: boolean;
platform?: DevicePlatform;
query?: string;
limit?: number;
offset?: number;
},
): Promise<{ devices: DeviceView[]; total: number }>listEnrollments
Lists the tenant's enrollment codes, newest first, without the codes themselves.
- Permission:
iam:devices:manageoniam/devices/enrollments. - Audited as:
iam:devices:manage.
Each entry has its status (pending, used or expired), the device and person it is for, and who created and
used it. The retention sweep deletes codes after they expire.
Prop
Type
An array of DeviceEnrollmentView.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/listEnrollments" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.listEnrollments(
credential: CredentialInput,
input: { tenantId: string },
): Promise<DeviceEnrollmentView[]>listIntegrations
Lists the tenant's MDM and EDR integrations by name, with the number of devices each manages.
- Permission:
iam:devices:readoniam/devices/integrations. - Audited as:
iam:devices:read.
Prop
Type
An array of DeviceIntegrationView.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/listIntegrations" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.listIntegrations(
credential: CredentialInput,
input: { tenantId: string },
): Promise<DeviceIntegrationView[]>mine
Lists the caller's devices that are not retired, each with its compliance and assurance, the device presenting this request first.
- Permission: None beyond a person's own sign-in session or API key in the tenant; also while impersonating.
- Audited as: Not audited; it only reads.
- Errors:
ACCESS_DENIEDfrom a role session, session token, delegated session, or a session of another tenant.
current marks the device whose proof this request carries. Use it for a "your devices" page.
Prop
Type
An array of MyDevice.
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/mine" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>"
}'iam.api.devices.mine(
credential: CredentialInput,
input: { tenantId: string },
): Promise<MyDevice[]>removeKey
Removes one enrolled key from a device, such as a lost browser profile or a replaced agent.
- Permission:
iam:devices:manageoniam/devices/{id}, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:key-remove. - Errors:
NOT_FOUNDwhen the key is not enrolled on that device;RECENT_AUTH_REQUIRED.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/removeKey" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"deviceId": "<deviceId>",
"keyId": "<keyId>"
}'iam.api.devices.removeKey(
credential: CredentialInput,
input: { tenantId: string; deviceId: string; keyId: string },
): Promise<{ success: true }>report
Creates or updates up to 500 devices with their posture, as reported by an integration, all or nothing.
- Permission:
iam:devices:reportoniam/devices/integrations/{id}; no recent sign-in, so a service account's API key can call it. - Audited as:
iam:devices:report;device:reportonce per call with the counts; anddevice:compliance-changefor each existing device whose compliance flipped. - Errors:
INVALID_INPUTfor an empty list or more than 500 devices, a missing, malformed or repeatedexternalId, an unknown platform or field, a posture value that is not a boolean, anosVersionover 64 characters, a malformedkeyThumbprint, or acheckedInAtmore than five minutes ahead;INVALID_TRANSITION(409) when the integration is disabled;NOT_FOUNDwhen the integration is not in this tenant.
Devices are matched by the vendor's externalId and created on first sight. null and empty strings count as absent.
Each report replaces the device's posture, so a field left out becomes unknown. A named owner (ownerIdentityId or
ownerEmail, a person of the tenant) is set, an unknown one leaves the device without an owner, and a report that
names none keeps the current one. osVersion keeps its leading dotted number (14.5 (23F79) reads as 14.5).
keyThumbprint moves a key already enrolled in the tenant onto the reported device, retiring the same person's
self-enrolled record of the machine when that record has no keys left. It moves only from an active device of the
reported owner that is self-enrolled or this integration's own: a key on a lost, shared, or someone else's device, or on
a device another integration manages, stays where it is. Reports older than a device's last check-in are ignored,
identical check-ins are written at most once a minute (always when they change the device's compliance), and reports
never change a device's status. The answer counts created, updated, unchanged and complianceChanged devices.
await iam.api.devices.report(
{ token: reporterKey },
{
tenantId,
integrationId,
devices: [
{
externalId: 'jamf-42',
name: 'MBP-ALICE',
platform: 'macos',
serialNumber: 'C02XYZ123',
osVersion: '14.5 (23F79)',
ownerEmail: 'alice@acme.test',
posture: { compliant: true, encrypted: true, firewall: true, screenLock: true },
},
],
},
);Prop
Type
A DeviceReportResult object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/report" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"integrationId": "<integrationId>",
"devices": [
{
"externalId": "<externalId>",
"platform": "other",
"posture": {}
}
]
}'iam.api.devices.report(
credential: CredentialInput,
input: { tenantId: string; integrationId: string; devices: DeviceReport[] },
): Promise<DeviceReportResult>retire
Retires a device for good, deleting its keys and pending enrollment codes.
- Permission:
iam:devices:manageoniam/devices/{id}, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:retirewithself: false. - Errors:
INVALID_TRANSITION(409) when it is already retired;RECENT_AUTH_REQUIRED;NOT_FOUND.
A retired device proves nothing, and later integration reports keep it retired.
Prop
Type
A DeviceView object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/retire" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"deviceId": "<deviceId>"
}'iam.api.devices.retire(
credential: CredentialInput,
input: { tenantId: string; deviceId: string },
): Promise<DeviceView>retireMine
Retires one of the caller's own unmanaged devices and deletes its keys.
- Permission: None beyond a person's own sign-in session or API key in the tenant, with a recent sign-in; never while impersonating.
- Audited as:
device:retirewithself: true. - Errors:
NOT_FOUNDwhen the device is not the caller's;INVALID_TRANSITION(409) for a managed device (an administrator retires those) or one already retired;IMPERSONATION_RESTRICTED;RECENT_AUTH_REQUIRED;ACCESS_DENIEDfrom another kind of session.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/retireMine" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"deviceId": "<deviceId>"
}'iam.api.devices.retireMine(
credential: CredentialInput,
input: { tenantId: string; deviceId: string },
): Promise<{ success: true; keysRemoved: number }>revokeEnrollment
Withdraws an enrollment code, used or not.
- Permission:
iam:devices:manageoniam/devices/enrollments. - Audited as:
iam:devices:manage, plusdevice:enrollment-revoke. - Errors:
NOT_FOUNDwhen the code is not in this tenant.
Prop
Type
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/revokeEnrollment" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"enrollmentId": "<enrollmentId>"
}'iam.api.devices.revokeEnrollment(
credential: CredentialInput,
input: { tenantId: string; enrollmentId: string },
): Promise<{ success: true }>update
Renames a device, changes its owner, or marks it lost or active again.
- Permission:
iam:devices:manageoniam/devices/{id}, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:updatewith the name, status and owner before and after. - Errors:
INVALID_INPUTwithout a name, owner or status to change, for an unknown field, a status other thanactiveorlost, or an owner who is not a person of the tenant;INVALID_TRANSITION(409) for a retired device;RECENT_AUTH_REQUIRED;NOT_FOUND.
ownerIdentityId: null makes the device shared, so any member of the tenant may present it. A new owner drops the keys
the previous owner enrolled. A lost device proves nothing until it is marked active again.
Prop
Type
A DeviceView object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/update" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"deviceId": "<deviceId>"
}'iam.api.devices.update(
credential: CredentialInput,
input: {
tenantId: string;
deviceId: string;
name?: string;
ownerIdentityId?: string | null;
status?: 'active' | 'lost';
},
): Promise<DeviceView>updateIntegration
Renames an integration, disables or enables it, or changes whether the vendor's verdict counts.
- Permission:
iam:devices:manageoniam/devices/integrations/{id}, and a recent sign-in. - Audited as:
iam:devices:manage, plusdevice:integration-updatewith the settings before and after. - Errors:
CONFLICT(409) for a name in use;INVALID_INPUTfor a status other thanactiveordisabled, or an unknown field;NOT_FOUND;RECENT_AUTH_REQUIRED.
While an integration is disabled its devices do not count as managed, and its reports are refused.
Prop
Type
A DeviceIntegrationView object:
Prop
Type
Example HTTP request
Only the required fields are shown; replace each <placeholder>. The response is { "data": … } on success or { "error": { "code", "message" } }.
curl -X POST "$IAM_URL/api/iam/devices/updateIntegration" \
-H "Authorization: Bearer $BETTER_IAM_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Better-IAM: 1" \
-d '{
"tenantId": "<tenantId>",
"integrationId": "<integrationId>"
}'iam.api.devices.updateIntegration(
credential: CredentialInput,
input: {
tenantId: string;
integrationId: string;
name?: string;
status?: 'active' | 'disabled';
trustVendorCompliance?: boolean;
},
): Promise<DeviceIntegrationView>Better IAM is created by Sean Filimon
Last updated