<!-- Device Inventory Manager — https://wiki.cyberguard.srl/dim/api/endpoints/ -->

# Endpoints

All endpoints are read-only and return JSON. Dates are in **UTC**, ISO 8601 format (for example `2026-10-14T09:05:48Z`).

The full machine-readable reference (OpenAPI) is available at:

```text
https://inventory-api.cyberguard.srl/openapi/v1.json
```

| Method | Path | Scope |
|--------|------|-------|
| `GET` | `/v1/devices` | `devices.read` |
| `GET` | `/v1/devices/{id}` | `devices.read` |
| `GET` | `/v1/compliance/devices` | `compliance.read` |
| `GET` | `/v1/compliance/summary` | `compliance.read` |
| `GET` | `/v1/audit-log` | `audit.read` |

---

## Lists and pagination

List endpoints return one page at a time:

```json
{
  "data": [ ... ],
  "nextCursor": "MTpiZWE0N2VhNWM4ZTA0NWY4YTM5NjQwYmEwZjA0ZmJmYg",
  "count": 500
}
```

To get the next page, pass `nextCursor` as `cursor`. When `nextCursor` is `null`, there are no more pages.

| Parameter | Description |
|-----------|-------------|
| `pageSize` | Records per page, from 1 to 500. Default 100 |
| `cursor` | Value of `nextCursor` from the previous page |

Use `pageSize=500` to minimise the number of calls. A list of 2,000 devices takes 4 calls.

---

## Devices

`GET /v1/devices` and `GET /v1/devices/{id}`

| Filter | Description |
|--------|-------------|
| `serialNumber` | Exact serial number |
| `intuneDeviceId` | Exact Microsoft Intune device ID |
| `modifiedSince` | Only devices updated after this date (ISO 8601). Device data is refreshed at every synchronisation, so this returns the devices touched by the latest sync |

| Field | Description |
|-------|-------------|
| `id` | Device ID in the portal |
| `subTenantId` | Sub-tenant the device belongs to, if any |
| `intuneDeviceId`, `entraDeviceId` | Microsoft Intune and Entra IDs |
| `deviceName`, `serialNumber`, `manufacturer`, `model` | Identification |
| `operatingSystem`, `osVersion`, `osEdition` | Operating system |
| `cpuArchitecture`, `tpmVersion`, `biosVersion`, `biosReleaseDate` | Hardware and firmware |
| `physicalMemoryGb`, `totalStorageGb`, `freeStorageGb` | Memory and storage |
| `deviceType`, `ownership`, `managementState`, `enrollmentType`, `joinType` | Management |
| `primaryUserUpn`, `primaryUserDisplayName`, `primaryUserEmail` | Primary user |
| `complianceState`, `isEncrypted` | Compliance and encryption |
| `source` | `MicrosoftIntune` or `Standalone` |
| `lifecycleStatus`, `conditionStatus`, `site`, `tag` | Lifecycle data set in the portal |
| `agentVersion`, `lastAgentAssessmentDateTime` | CyberGuard agent |
| `lastSyncDateTime`, `enrolledDateTime`, `discoveredDateTime`, `updatedDateTime` | Dates |

---

## Compliance

`GET /v1/compliance/devices` returns, for each device: `deviceId`, `subTenantId`, `deviceName`, `serialNumber`, `operatingSystem`, `osVersion`, `primaryUserUpn`, `complianceState`, `isEncrypted`, `lastSyncDateTime`, `updatedDateTime`. It accepts the same filters as `/v1/devices`.

`GET /v1/compliance/summary` returns the totals of the tenant:

```json
{
  "totalDevices": 9,
  "byState": { "compliant": 5, "noncompliant": 4 },
  "encrypted": 8,
  "notEncrypted": 1,
  "encryptionUnknown": 0
}
```

---

## Audit log

`GET /v1/audit-log` returns the same entries shown in the **Audit log** tab of the portal: the activity of your users and of your API clients. Entries are returned oldest first.

| Filter | Description |
|--------|-------------|
| `from`, `to` | Time range (ISO 8601, UTC) |
| `category` | `Access`, `Navigation`, `Devices`, `ExtraDevices`, `Inventory`, `ImportExport`, `Assignments`, `Administration`, `Other` |

| Field | Description |
|-------|-------------|
| `id` | Entry ID, always increasing |
| `createdDateTime` | Date and time (UTC) |
| `category`, `action` | Type of activity |
| `userEmail`, `userDisplayName` | Portal user. Empty for API client entries |
| `entityType`, `entityId` | Object involved. For API clients: `ApiClient` and the Client ID |
| `details` | Description of the activity |
| `ipAddress` | Source IP address |

### SIEM integration

> **Audit entries are kept for 60 days.** Collect them regularly, for example every hour.

Store the last `nextCursor` (or the last `id` received) and resume from there at the next run. Collected entries are never returned twice.

---

## Responses and errors

Every `/v1` response includes:

| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit` | Daily call quota of the tenant |
| `X-RateLimit-Remaining` | Calls left today |
| `X-RateLimit-Reset` | Seconds until the daily quota resets (midnight in your time zone) |

Errors use the standard problem format (`application/problem+json`) and include a `traceId`. Send it to support if you need help.

| Status | Meaning |
|--------|---------|
| `400` | Invalid parameter (cursor, pageSize, date or category) |
| `401` | Missing, expired or invalid token, client revoked, or API add-on no longer active |
| `403` | The token does not include the scope required by the endpoint, or the feature is not included in your license |
| `404` | Record not found |
| `429` | Rate limit or quota exceeded. Wait for the seconds in `Retry-After` |
| `503` | Service temporarily unavailable. Retry after the seconds in `Retry-After` |
